This is an automated email from the ASF dual-hosted git repository.
github-merge-queue[bot] pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/texera.git
The following commit(s) were added to refs/heads/main by this push:
new fe9c490023 refactor(frontend): remove dead getPrevStats and the
redundant search-cache index (#7038)
fe9c490023 is described below
commit fe9c4900234f535ae80fb002138f8c9386e68bb8
Author: Xinyuan Lin <[email protected]>
AuthorDate: Wed Jul 29 19:36:07 2026 -0700
refactor(frontend): remove dead getPrevStats and the redundant search-cache
index (#7038)
### What changes were proposed in this PR?
Removes two pieces of frontend state that are maintained but not needed.
No behaviour change.
**1. `OperatorPaginationResultService.getPrevStats` is dead API.**
`getPrevStats()` has no caller in `src/` — not from TypeScript, not from
a template. Its backing field `prevStatsCache` exists only to feed it,
so the whole rotate-into-the-previous-slot dance in `handleStatsUpdate`
serves a reader that does not exist. The `if (!this.statsCache)` branch
is also unreachable: `statsCache` is initialised to `{}` and only ever
reassigned to another object.
```ts
// before
public handleStatsUpdate(statsUpdate): void {
if (!this.statsCache) {
this.statsCache = statsUpdate;
this.prevStatsCache = statsUpdate;
} else {
this.prevStatsCache = this.statsCache;
this.statsCache = statsUpdate;
}
}
// after
public handleStatsUpdate(statsUpdate): void {
this.statsCache = statsUpdate;
}
```
This does **not** touch `WorkflowResultService.getResultTableStats()`,
which is the mechanism actually used to deliver previous/current stats
pairs to the UI (via rxjs `pairwise()`).
**2. `SearchBarComponent.queryOrder` duplicates `Map` insertion order.**
The search cache kept a parallel `string[]` purely to know which key to
evict next. A JavaScript `Map` already iterates in insertion order, and
`addToCache` is only reached on a cache **miss** (a hit returns early at
`getSearchResults`), so the array can never diverge from the Map's own
key order — the oldest key is always `searchCache.keys().next().value`.
```ts
// before
if (this.queryOrder.length >= 20) {
const oldestQuery = this.queryOrder.shift();
this.searchCache.delete(oldestQuery!);
}
this.queryOrder.push(query);
this.searchCache.set(query, results);
// after
if (this.searchCache.size >= 20) {
const oldestQuery = this.searchCache.keys().next().value;
this.searchCache.delete(oldestQuery!);
}
this.searchCache.set(query, results);
```
Both existing tests were kept and re-pointed at the surviving API rather
than dropped, so eviction order and stats replacement are still pinned.
−23 lines, +13.
### Any related issues, documentation, discussions?
Closes #7037
### How was this PR tested?
Existing tests, updated in place to assert the same behaviour through
the surviving API:
- `search-bar.component.spec.ts` — the eviction test now reads
`[...cache.keys()]` instead of the removed `queryOrder` array. Same
assertions: `q0` evicted, `q1` oldest, `q20` newest, size stays 20.
- `workflow-result.service.spec.ts` — `handleStatsUpdate` is now
asserted to replace the current stats (it no longer has a previous slot
to rotate into).
Locally:
- `npx tsc --noEmit -p frontend/tsconfig.json` — exit 0.
- `ng test --watch=false --include='**/search-bar.component.spec.ts'
--include='**/workflow-result.service.spec.ts'` — 39 tests, all pass.
- `prettier-eslint --list-different
"src/**/*.{ts,js,html,scss,less,json}"` — no differences.
Verification that nothing references the removed members:
```
grep -rn "prevStatsCache\|getPrevStats\|queryOrder" frontend/src
```
### Was this PR authored or co-authored using generative AI tooling?
Generated-by: Claude Code (Claude Opus 5)
---
.../component/user/search-bar/search-bar.component.spec.ts | 9 +++++----
.../component/user/search-bar/search-bar.component.ts | 8 ++++----
.../service/workflow-result/workflow-result.service.spec.ts | 6 +++---
.../service/workflow-result/workflow-result.service.ts | 13 +------------
4 files changed, 13 insertions(+), 23 deletions(-)
diff --git
a/frontend/src/app/dashboard/component/user/search-bar/search-bar.component.spec.ts
b/frontend/src/app/dashboard/component/user/search-bar/search-bar.component.spec.ts
index 2540e89d2b..71b7573cf5 100644
---
a/frontend/src/app/dashboard/component/user/search-bar/search-bar.component.spec.ts
+++
b/frontend/src/app/dashboard/component/user/search-bar/search-bar.component.spec.ts
@@ -149,22 +149,23 @@ describe("SearchBarComponent", () => {
it("addToCache evicts the oldest entry once 20 queries are cached", () => {
const cache = (component as any).searchCache as Map<string, string[]>;
- const order = (component as any).queryOrder as string[];
for (let i = 0; i < 20; i++) {
(component as any).addToCache(`q${i}`, [`r${i}`]);
}
expect(cache.size).toBe(20);
expect(cache.has("q0")).toBe(true);
- expect(order[0]).toBe("q0");
+ expect([...cache.keys()][0]).toBe("q0");
(component as any).addToCache("q20", ["r20"]);
expect(cache.size).toBe(20);
expect(cache.has("q0")).toBe(false);
expect(cache.has("q20")).toBe(true);
- expect(order[0]).toBe("q1");
- expect(order[order.length - 1]).toBe("q20");
+ // The Map's own iteration order is the eviction order.
+ const keys = [...cache.keys()];
+ expect(keys[0]).toBe("q1");
+ expect(keys[keys.length - 1]).toBe("q20");
});
describe("convertToName", () => {
diff --git
a/frontend/src/app/dashboard/component/user/search-bar/search-bar.component.ts
b/frontend/src/app/dashboard/component/user/search-bar/search-bar.component.ts
index 638a2f7e7b..83cabf089a 100644
---
a/frontend/src/app/dashboard/component/user/search-bar/search-bar.component.ts
+++
b/frontend/src/app/dashboard/component/user/search-bar/search-bar.component.ts
@@ -69,7 +69,6 @@ export class SearchBarComponent {
};
private searchCache = new Map<string, string[]>();
- private queryOrder: string[] = [];
constructor(
private router: Router,
@@ -119,12 +118,13 @@ export class SearchBarComponent {
}
}
+ // A Map iterates in insertion order, and addToCache is only reached on a
cache
+ // miss, so the oldest key is always the first one.
private addToCache(query: string, results: string[]): void {
- if (this.queryOrder.length >= 20) {
- const oldestQuery = this.queryOrder.shift();
+ if (this.searchCache.size >= 20) {
+ const oldestQuery = this.searchCache.keys().next().value;
this.searchCache.delete(oldestQuery!);
}
- this.queryOrder.push(query);
this.searchCache.set(query, results);
}
diff --git
a/frontend/src/app/workspace/service/workflow-result/workflow-result.service.spec.ts
b/frontend/src/app/workspace/service/workflow-result/workflow-result.service.spec.ts
index 8ed9d41b4a..e73f28b39a 100644
---
a/frontend/src/app/workspace/service/workflow-result/workflow-result.service.spec.ts
+++
b/frontend/src/app/workspace/service/workflow-result/workflow-result.service.spec.ts
@@ -421,17 +421,17 @@ describe("OperatorPaginationResultService", () => {
});
describe("handleStatsUpdate", () => {
- it("rotates the current stats into the previous slot on each update", ()
=> {
+ it("replaces the current stats on each update", () => {
const first = { colA: { count: 1 } };
const second = { colA: { count: 2 } };
+ expect(service.getStats()).toEqual({});
+
service.handleStatsUpdate(first);
expect(service.getStats()).toEqual(first);
- expect(service.getPrevStats()).toEqual({});
service.handleStatsUpdate(second);
expect(service.getStats()).toEqual(second);
- expect(service.getPrevStats()).toEqual(first);
});
});
diff --git
a/frontend/src/app/workspace/service/workflow-result/workflow-result.service.ts
b/frontend/src/app/workspace/service/workflow-result/workflow-result.service.ts
index ffd9b43b91..26133a636e 100644
---
a/frontend/src/app/workspace/service/workflow-result/workflow-result.service.ts
+++
b/frontend/src/app/workspace/service/workflow-result/workflow-result.service.ts
@@ -273,7 +273,6 @@ export class OperatorResultService {
export class OperatorPaginationResultService {
private pendingRequests: Map<string, Subject<PaginatedResultEvent>> = new
Map();
private resultCache: Map<number, ReadonlyArray<object>> = new Map();
- private prevStatsCache: Record<string, Record<string, number>> = {};
private statsCache: Record<string, Record<string, number>> = {};
private currentPageIndex: number = 1;
private currentTotalNumTuples: number = 0;
@@ -293,10 +292,6 @@ export class OperatorPaginationResultService {
return this.statsCache;
}
- public getPrevStats(): Record<string, Record<string, number>> {
- return this.prevStatsCache;
- }
-
public getCurrentPageIndex(): number {
return this.currentPageIndex;
}
@@ -378,13 +373,7 @@ export class OperatorPaginationResultService {
}
public handleStatsUpdate(statsUpdate: Record<string, Record<string,
number>>): void {
- if (!this.statsCache) {
- this.statsCache = statsUpdate;
- this.prevStatsCache = statsUpdate;
- } else {
- this.prevStatsCache = this.statsCache;
- this.statsCache = statsUpdate;
- }
+ this.statsCache = statsUpdate;
}
private handlePaginationResult(res: PaginatedResultEvent): void {