You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@texera.apache.org by gi...@apache.org on 2026/08/22 07:20:07 UTC

(texera) branch main updated: chore(frontend, amber): remove the unreachable available-result event and orphaned list item (#7783)

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 8ca9db2005 chore(frontend, amber): remove the unreachable available-result event and orphaned list item (#7783)
8ca9db2005 is described below

commit 8ca9db20051f1ba7e4ee59e164655cf55a6bd1ee
Author: Xinyuan Lin <xi...@uci.edu>
AuthorDate: Sat Aug 22 06:58:53 2026 +0000

    chore(frontend, amber): remove the unreachable available-result event and orphaned list item (#7783)
    
    ### What changes were proposed in this PR?
    
    Removes three unreachable pieces of code. **998 lines deleted, 1
    added.**
    
    **1. `WorkflowAvailableResultEvent` and its dangling client handler.**
    Nothing in `src/main` constructs the event, and it is not among the 11
    `classOf[...]` entries in `TexeraWebSocketEvent.scala`'s
    `@JsonSubTypes`, so it is not reflectively dispatched either. Yet
    `workflow-result.service.ts` still subscribed to
    `"WorkflowAvailableResultEvent"` and routed it to
    `handleCleanResultCache` — a handler the backend could never trigger.
    
    A second signal that this path was never live: the TypeScript type
    declared `availableOperators` as
    `ReadonlyArray<OperatorAvailableResult>`, while both the Scala event and
    the handler treat it as a keyed map (`Map[String,
    OperatorAvailableResult]` / `Object.entries(...)`). The declared wire
    shape matched neither producer nor consumer.
    
    Removed: the Scala event, the frontend subscription,
    `handleCleanResultCache`, the orphaned TS types and their
    `TexeraWebsocketEventTypeMap` entry, and a then-unused `WebOutputMode`
    import.
    
    **2. `UserDatasetListItemComponent` is orphaned.** Its selector appears
    repo-wide only in its own `@Component` declaration and its own spec's
    test host. The single other reference was a standalone entry in
    `app.module.ts`'s `imports` array with no consumer — and since
    `declarations` is `[AppComponent]` only, being in `imports` merely
    exposes it to `AppComponent`'s template, where the selector does not
    appear. The dataset page moved to
    `texera-card-item`/`texera-search-results` in #5947.
    
    Checked beyond the selector, because a component can be reached
    indirectly: only two `@NgModule`s exist in the app, no
    `loadChildren`/`loadComponent` lazy routes reference it, and there is no
    `createComponent`/`ngComponentOutlet`/`ComponentFactoryResolver`
    instantiation.
    
    Removed the `.ts`, `.html`, `.scss`, its spec, and both `app.module.ts`
    lines.
    
    **3. `DynamicSchemaService.dynamicSchemaExists`** — exactly one
    occurrence repo-wide, its own declaration, while every sibling method
    has 2 to 5 call sites.
    
    ### Two tests were removed, deliberately
    
    Two cases in `workflow-result.service.spec.ts` existed *solely* to
    exercise `handleCleanResultCache`, by pushing a synthetic event directly
    onto the socket subject. Their own fixtures are corroborating evidence:
    they pass `availableOperators` as a keyed object — matching the Scala
    type and the handler — while the declared TS type said array. They could
    not have been written from a real frame.
    
    The `user-dataset-list-item` spec went with its component for the same
    reason.
    
    A stale scaladoc paragraph in `TexeraWebSocketEventSpec.scala` also
    named this event, noting that "nothing in main constructs it, so pinning
    its wire shape would only cement dead code" — an independent
    confirmation of the finding from an earlier reviewer. That paragraph is
    removed; the preceding one, which lists the five genuinely unregistered
    producers, stays accurate. No count or reflection assertion depended on
    it.
    
    ### Verification
    
    - Full frontend suite: **200 files, 4708 passed, 1 skipped, 0 failed.**
    - Amber `TexeraWebSocketEventSpec`: main and test compiled with no
    errors, **10/10 passed**. Compiling clean is itself the proof that
    nothing in amber referenced the deleted class.
    - **AOT `ng build` succeeded** — this matters, because `ng test` and
    `tsc --noEmit` both miss Angular template errors, so a removed component
    could otherwise break the build silently. Bundle generation completed
    with zero `NG####` diagnostics and zero errors referencing `src/`. The
    build's exit code is 1 from exactly the 13 pre-existing monaco webpack
    loader failures on `node_modules` assets, which are unrelated to this
    change.
    - `yarn format:ci` exits 0; `scalafmtCheck`, `Test/scalafmtCheck` and
    `scalafixAll --check` all pass — no imports were left orphaned.
    - Residual-reference greps for both removed symbols come back empty.
    
    ### Any related issues, documentation, discussions?
    
    Closes #7782
    
    ### How was this PR tested?
    
    ```
    npx ng test --watch=false
    ```
    
    ```
     Test Files  200 passed (200)
          Tests  4708 passed | 1 skipped (4709)
    ```
    
    ### Was this PR authored or co-authored using generative AI tooling?
    
    Generated-by: Claude Code (Opus 5)
---
 .../event/WorkflowAvailableResultEvent.scala       |  34 --
 .../websocket/event/TexeraWebSocketEventSpec.scala |   4 -
 frontend/src/app/app.module.ts                     |   2 -
 .../user-dataset-list-item.component.html          | 154 --------
 .../user-dataset-list-item.component.scss          |  87 -----
 .../user-dataset-list-item.component.spec.ts       | 424 ---------------------
 .../user-dataset-list-item.component.ts            | 180 ---------
 .../dynamic-schema/dynamic-schema.service.ts       |   4 -
 .../workflow-result.service.spec.ts                |  51 ---
 .../workflow-result/workflow-result.service.ts     |  47 +--
 .../types/workflow-websocket.interface.ts          |  12 -
 11 files changed, 1 insertion(+), 998 deletions(-)

diff --git a/amber/src/main/scala/org/apache/texera/web/model/websocket/event/WorkflowAvailableResultEvent.scala b/amber/src/main/scala/org/apache/texera/web/model/websocket/event/WorkflowAvailableResultEvent.scala
deleted file mode 100644
index bc9e006cd3..0000000000
--- a/amber/src/main/scala/org/apache/texera/web/model/websocket/event/WorkflowAvailableResultEvent.scala
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-package org.apache.texera.web.model.websocket.event
-
-import org.apache.texera.web.model.websocket.event.WorkflowAvailableResultEvent.OperatorAvailableResult
-import org.apache.texera.web.service.ExecutionResultService.WebOutputMode
-
-object WorkflowAvailableResultEvent {
-  case class OperatorAvailableResult(
-      cacheValid: Boolean,
-      outputMode: WebOutputMode
-  )
-}
-
-case class WorkflowAvailableResultEvent(
-    availableOperators: Map[String, OperatorAvailableResult]
-) extends TexeraWebSocketEvent
diff --git a/amber/src/test/scala/org/apache/texera/web/model/websocket/event/TexeraWebSocketEventSpec.scala b/amber/src/test/scala/org/apache/texera/web/model/websocket/event/TexeraWebSocketEventSpec.scala
index 6a1e063d59..b66d4d0c99 100644
--- a/amber/src/test/scala/org/apache/texera/web/model/websocket/event/TexeraWebSocketEventSpec.scala
+++ b/amber/src/test/scala/org/apache/texera/web/model/websocket/event/TexeraWebSocketEventSpec.scala
@@ -163,10 +163,6 @@ class TexeraWebSocketEventSpec extends AnyFlatSpec with Matchers {
     * `ExecutionStatsService` (duration), `RegionExecutionManager` (region state),
     * `ExecutionReconfigurationService` (modify-logic completed), `ClusterListener` /
     * `WorkflowWebsocketResource` (cluster status) and `Coordinator` (region update).
-    *
-    * `WorkflowAvailableResultEvent` is the sixth unregistered subtype but is deliberately
-    * absent from this list: nothing in main constructs it, so pinning its wire shape would
-    * only cement dead code.
     */
   private val outboundOnlyEvents: List[(String, TexeraWebSocketEvent)] = List(
     "ExecutionDurationUpdateEvent" -> ExecutionDurationUpdateEvent(1234L, isRunning = true),
diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts
index 19c94f3deb..0dfbd0c5ce 100644
--- a/frontend/src/app/app.module.ts
+++ b/frontend/src/app/app.module.ts
@@ -155,7 +155,6 @@ import { DatasetDetailComponent } from "./dashboard/component/user/user-dataset/
 import { UserDatasetVersionFiletreeComponent } from "./dashboard/component/user/user-dataset/user-dataset-explorer/user-dataset-version-filetree/user-dataset-version-filetree.component";
 import { UserDatasetFileRendererComponent } from "./dashboard/component/user/user-dataset/user-dataset-explorer/user-dataset-file-renderer/user-dataset-file-renderer.component";
 import { NzSpinModule } from "ng-zorro-antd/spin";
-import { UserDatasetListItemComponent } from "./dashboard/component/user/user-dataset/user-dataset-list-item/user-dataset-list-item.component";
 import { NgxFileDropModule } from "ngx-file-drop";
 import { NzTreeModule } from "ng-zorro-antd/tree";
 import { NzTreeViewModule } from "ng-zorro-antd/tree-view";
@@ -322,7 +321,6 @@ registerLocaleData(en);
     UserDatasetVersionCreatorComponent,
     DatasetDetailComponent,
     UserDatasetVersionFiletreeComponent,
-    UserDatasetListItemComponent,
     UserDatasetFileRendererComponent,
     UserDatasetStagedObjectsListComponent,
     NzModalCommentBoxComponent,
diff --git a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-list-item/user-dataset-list-item.component.html b/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-list-item/user-dataset-list-item.component.html
deleted file mode 100644
index 1383680f8f..0000000000
--- a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-list-item/user-dataset-list-item.component.html
+++ /dev/null
@@ -1,154 +0,0 @@
-<!--
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements.  See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership.  The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License.  You may obtain a copy of the License at
-
-   http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied.  See the License for the
- specific language governing permissions and limitations
- under the License.
--->
-
-<nz-list-item class="dataset-list-item">
-  <nz-list-item-meta class="dataset-item-meta">
-    <!-- Margin need only when the checkbox is not visible -->
-    <nz-list-item-meta-avatar [ngStyle]="{ 'margin-left': editable ? 'none' : '16px' }">
-      <nz-avatar
-        [ngStyle]="{ 'background-color': 'grey', 'vertical-align': 'middle' }"
-        [nzGap]="4"
-        [nzText]="'' + dataset.did"
-        nzSize="default"></nz-avatar>
-    </nz-list-item-meta-avatar>
-
-    <!-- editable name of saved dataset -->
-    <nz-list-item-meta-title class="meta-title-container">
-      <div class="dataset-item-meta-title">
-        <a
-          *ngIf="!editingName; else customDatasetTitle "
-          [routerLink]="USER_DATASET + '/' + dataset.did"
-          class="dataset-name"
-          >{{ dataset.name }}</a
-        >
-        <ng-template #customDatasetTitle>
-          <input
-            #customName
-            (focusout)="confirmUpdateDatasetCustomName(customName.value)"
-            (keyup.enter)="confirmUpdateDatasetCustomName(customName.value)"
-            placeholder="{{ dataset.name }}"
-            value="{{ dataset.name }}" />
-        </ng-template>
-        <button
-          *ngIf="editable && entry.accessPrivilege === 'WRITE'"
-          (click)="editingName = true"
-          nz-button
-          mat-card-title="Customize Dataset Name"
-          nz-tooltip="Customize Dataset Name"
-          nzSize="small"
-          nzTooltipPlacement="bottom"
-          nzType="text">
-          <i
-            nz-icon
-            nzTheme="outline"
-            nzType="edit"></i>
-        </button>
-        <button
-          *ngIf="editable && entry.accessPrivilege === 'WRITE'"
-          (click)="editingDescription = true"
-          nz-button
-          nz-tooltip="Add Description"
-          nzSize="small"
-          nzTooltipPlacement="bottom"
-          nzType="text"
-          class="add-description-btn">
-          <i
-            nz-icon
-            nzTheme="outline"
-            nzType="plus-square"></i>
-        </button>
-        <i
-          class="dataset-is-owner-icon"
-          *ngIf="entry.isOwner"
-          nz-tooltip="You are the owner"
-          nzTooltipPlacement="bottom"
-          nz-icon
-          nzTheme="outline"
-          nzType="user"></i>
-        <i
-          *ngIf="!entry.isOwner"
-          nz-tooltip="{{
-                                  entry.accessPrivilege
-                              }} Access"
-          nzTooltipPlacement="bottom"
-          nz-icon
-          nzTheme="outline"
-          nzType="team"></i>
-      </div>
-    </nz-list-item-meta-title>
-
-    <!-- editable description of saved dataset -->
-    <nz-list-item-meta-description>
-      <div class="dataset-item-meta-description">
-        <label
-          *ngIf="!editingDescription; else customDatasetDescription "
-          (click)="editingDescription = editable && entry.accessPrivilege === 'WRITE'"
-          class="dataset-description-label">
-          {{ dataset.description }}
-        </label>
-        <ng-template #customDatasetDescription>
-          <input
-            title="Description"
-            #customDescription
-            (focusout)="confirmUpdateDatasetCustomDescription(customDescription.value)"
-            (keyup.enter)="confirmUpdateDatasetCustomDescription(customDescription.value)"
-            class="dataset-editable-description-input"
-            value="{{ dataset.description }}"
-            maxlength="500" />
-        </ng-template>
-      </div>
-    </nz-list-item-meta-description>
-  </nz-list-item-meta>
-
-  <ul nz-list-item-actions>
-    <nz-list-item-action>
-      <button
-        (click)="onClickOpenShareAccess()"
-        nz-button
-        nz-tooltip="Share the dataset {{
-                      dataset.name
-                  }} to others"
-        nzTooltipPlacement="bottom"
-        type="button">
-        <i
-          nz-icon
-          nzTheme="outline"
-          nzType="share-alt"></i>
-      </button>
-    </nz-list-item-action>
-    <nz-list-item-action *ngIf="editable">
-      <button
-        (nzOnConfirm)="deleted.emit()"
-        nz-popconfirm
-        nzPopconfirmTitle="Confirm to delete this dataset."
-        [disabled]="!entry.isOwner"
-        class="delete-dataset-btn"
-        nz-button
-        nz-tooltip="Delete the dataset {{
-                      dataset.name
-                  }}"
-        nzTooltipPlacement="bottom">
-        <i
-          nz-icon
-          nzTheme="outline"
-          nzType="delete"></i>
-      </button>
-    </nz-list-item-action>
-  </ul>
-</nz-list-item>
diff --git a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-list-item/user-dataset-list-item.component.scss b/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-list-item/user-dataset-list-item.component.scss
deleted file mode 100644
index daabfebd53..0000000000
--- a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-list-item/user-dataset-list-item.component.scss
+++ /dev/null
@@ -1,87 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-@use "../../../section-style" as *;
-@use "../../../dashboard.component.scss" as *;
-
-/**
-  * css for project label, shared by workflow section and file section
-**/
-.dataset-list-item {
-  margin-bottom: 10px;
-  min-height: 70px;
-  padding: 5px 0 5px 0;
-
-  .dataset-item-meta {
-    margin: 0 20px;
-  }
-
-  .dataset-item-meta-title {
-    display: flex;
-    align-items: center;
-
-    .dataset-name {
-      color: black;
-      font-size: 20px;
-      font-family: -apple-system, BlinkMacSystemFont, sans-serif;
-      text-align: center;
-    }
-
-    i {
-      position: relative;
-      font-size: 17px;
-      margin-bottom: 6px;
-    }
-
-    i.dataset-is-owner-icon {
-      margin-left: 7px;
-    }
-  }
-
-  .dataset-item-meta-description {
-    display: flex;
-    align-items: center;
-    padding: 2px 8px 2px 10px;
-    margin-bottom: 8px;
-
-    .dataset-description-label {
-      font-size: 13px;
-      font-family: -apple-system, BlinkMacSystemFont, sans-serif;
-
-      display: inline-block;
-      min-width: 17ch;
-      border: 0 none;
-      outline: none;
-
-      &:hover {
-        cursor: pointer;
-        box-shadow: 0 0 0 1px rgb(202, 202, 202);
-      }
-    }
-
-    .dataset-editable-description-input {
-      margin-bottom: 5px;
-      display: inline-block;
-      min-width: 17ch;
-      border: 0 none;
-      outline: none;
-      box-shadow: 0 0 0 2px #007bff;
-    }
-  }
-}
diff --git a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-list-item/user-dataset-list-item.component.spec.ts b/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-list-item/user-dataset-list-item.component.spec.ts
deleted file mode 100644
index b023f10f3f..0000000000
--- a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-list-item/user-dataset-list-item.component.spec.ts
+++ /dev/null
@@ -1,424 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { Component, EventEmitter, ViewChild } from "@angular/core";
-import { ComponentFixture, TestBed } from "@angular/core/testing";
-import { By } from "@angular/platform-browser";
-import { HttpClientTestingModule } from "@angular/common/http/testing";
-import { provideRouter } from "@angular/router";
-import { NzListComponent } from "ng-zorro-antd/list";
-import { NzModalService } from "ng-zorro-antd/modal";
-import { NzTooltipDirective } from "ng-zorro-antd/tooltip";
-import { of, throwError } from "rxjs";
-import type { Mocked } from "vitest";
-import { UserDatasetListItemComponent } from "./user-dataset-list-item.component";
-import { DatasetService } from "../../../../service/user/dataset/dataset.service";
-import { NotificationService } from "../../../../../common/service/notification/notification.service";
-import { ShareAccessComponent } from "../../share-access/share-access.component";
-import { DashboardDataset } from "../../../../type/dashboard-dataset.interface";
-import { commonTestProviders } from "../../../../../common/testing/test-utils";
-
-// UserDatasetListItemComponent is rooted at <nz-list-item>; instantiating it
-// outside an <nz-list> host throws "No provider found for NzListComponent".
-@Component({
-  standalone: true,
-  imports: [NzListComponent, UserDatasetListItemComponent],
-  template: `
-    <nz-list>
-      <texera-user-dataset-list-item
-        [entry]="entry"
-        [editable]="editable"></texera-user-dataset-list-item>
-    </nz-list>
-  `,
-})
-class TestHostComponent {
-  entry!: DashboardDataset;
-  editable = true;
-  @ViewChild(UserDatasetListItemComponent, { static: true }) inner!: UserDatasetListItemComponent;
-}
-
-function makeEntry(overrides: Partial<DashboardDataset> = {}): DashboardDataset {
-  return {
-    isOwner: true,
-    ownerEmail: "owner@example.com",
-    accessPrivilege: "WRITE",
-    size: 0,
-    dataset: {
-      did: 1,
-      ownerUid: 1,
-      name: "dataset-1",
-      isPublic: false,
-      isDownloadable: true,
-      storagePath: undefined,
-      description: "original description",
-      creationTime: 0,
-      coverImage: undefined,
-    },
-    ...overrides,
-  };
-}
-
-describe("UserDatasetListItemComponent", () => {
-  let component: UserDatasetListItemComponent;
-  let fixture: ComponentFixture<TestHostComponent>;
-  let datasetService: Mocked<DatasetService>;
-  let notificationService: Mocked<NotificationService>;
-  let modalService: NzModalService;
-
-  beforeEach(async () => {
-    const datasetServiceSpy = {
-      updateDatasetName: vi.fn(),
-      updateDatasetDescription: vi.fn(),
-    };
-    const notificationServiceSpy = {
-      error: vi.fn(),
-      success: vi.fn(),
-      info: vi.fn(),
-      warning: vi.fn(),
-      loading: vi.fn(),
-      blank: vi.fn(),
-    };
-
-    await TestBed.configureTestingModule({
-      imports: [TestHostComponent, HttpClientTestingModule],
-      providers: [
-        { provide: DatasetService, useValue: datasetServiceSpy },
-        { provide: NotificationService, useValue: notificationServiceSpy },
-        NzModalService,
-        provideRouter([]),
-        ...commonTestProviders,
-      ],
-    }).compileComponents();
-
-    datasetService = TestBed.inject(DatasetService) as unknown as Mocked<DatasetService>;
-    notificationService = TestBed.inject(NotificationService) as unknown as Mocked<NotificationService>;
-    modalService = TestBed.inject(NzModalService);
-  });
-
-  beforeEach(() => {
-    fixture = TestBed.createComponent(TestHostComponent);
-    fixture.componentInstance.entry = makeEntry();
-    fixture.componentInstance.editable = true;
-    fixture.detectChanges();
-    component = fixture.componentInstance.inner;
-  });
-
-  it("should create", () => {
-    expect(component).toBeTruthy();
-  });
-
-  describe("entry getter", () => {
-    it("throws when accessed before being set", () => {
-      // Build a bare component without going through the host (the host always
-      // assigns entry on first change detection).
-      const bare = new UserDatasetListItemComponent(
-        {} as NzModalService,
-        {} as DatasetService,
-        {} as NotificationService
-      );
-      expect(() => bare.entry).toThrowError("entry property must be provided to UserDatasetListItemComponent.");
-    });
-
-    it("returns the value once set", () => {
-      const entry = makeEntry({ accessPrivilege: "READ" });
-      const bare = new UserDatasetListItemComponent(
-        {} as NzModalService,
-        {} as DatasetService,
-        {} as NotificationService
-      );
-      bare.entry = entry;
-      expect(bare.entry).toBe(entry);
-    });
-  });
-
-  describe("dataset getter", () => {
-    it("returns entry.dataset when present", () => {
-      expect(component.dataset).toBe(component.entry.dataset);
-    });
-
-    it("throws when entry.dataset is missing", () => {
-      const bare = new UserDatasetListItemComponent(
-        {} as NzModalService,
-        {} as DatasetService,
-        {} as NotificationService
-      );
-      bare.entry = { ...makeEntry(), dataset: undefined as unknown as DashboardDataset["dataset"] };
-      expect(() => bare.dataset).toThrowError(
-        "Incorrect type of DashboardEntry provided to UserDatasetListItemComponent. Entry must be dataset."
-      );
-    });
-  });
-
-  describe("confirmUpdateDatasetCustomName", () => {
-    it("is a no-op when the name has not changed", () => {
-      const current = component.entry.dataset.name;
-      component.confirmUpdateDatasetCustomName(current);
-      expect(datasetService.updateDatasetName).not.toHaveBeenCalled();
-    });
-
-    it("updates the dataset name on success and clears editingName", () => {
-      const newName = "renamed-dataset";
-      component.editingName = true;
-      datasetService.updateDatasetName.mockReturnValue(of({} as Response));
-
-      component.confirmUpdateDatasetCustomName(newName);
-
-      expect(datasetService.updateDatasetName).toHaveBeenCalledExactlyOnceWith(1, newName);
-      expect(component.entry.dataset.name).toBe(newName);
-      expect(component.editingName).toBe(false);
-    });
-
-    it("notifies the user on error and still clears editingName", () => {
-      const originalName = component.entry.dataset.name;
-      component.editingName = true;
-      datasetService.updateDatasetName.mockReturnValue(throwError(() => new Error("boom")));
-
-      component.confirmUpdateDatasetCustomName("renamed-dataset");
-
-      expect(notificationService.error).toHaveBeenCalledExactlyOnceWith("boom");
-      expect(component.entry.dataset.name).toBe(originalName);
-      expect(component.editingName).toBe(false);
-    });
-
-    ["", "a/b", "has space", "名前"].forEach(invalidName => {
-      it(`rejects the invalid name '${invalidName}' without calling the service`, () => {
-        const originalName = component.entry.dataset.name;
-        component.editingName = true;
-
-        component.confirmUpdateDatasetCustomName(invalidName);
-
-        expect(datasetService.updateDatasetName).not.toHaveBeenCalled();
-        expect(notificationService.error).toHaveBeenCalledExactlyOnceWith(
-          "Invalid dataset name: only letters, numbers, underscores, and hyphens are allowed (max 128 characters)"
-        );
-        expect(component.entry.dataset.name).toBe(originalName);
-        expect(component.editingName).toBe(false);
-      });
-    });
-
-    it("surfaces the backend error message when the rename is rejected", () => {
-      const originalName = component.entry.dataset.name;
-      component.editingName = true;
-      datasetService.updateDatasetName.mockReturnValue(
-        throwError(() => ({ error: { message: "Dataset with the same name already exists" } }))
-      );
-
-      component.confirmUpdateDatasetCustomName("renamed-dataset");
-
-      expect(notificationService.error).toHaveBeenCalledExactlyOnceWith("Dataset with the same name already exists");
-      expect(component.entry.dataset.name).toBe(originalName);
-      expect(component.editingName).toBe(false);
-    });
-  });
-
-  describe("confirmUpdateDatasetCustomDescription", () => {
-    it("is a no-op when the description has not changed", () => {
-      const current = component.entry.dataset.description;
-      component.confirmUpdateDatasetCustomDescription(current);
-      expect(datasetService.updateDatasetDescription).not.toHaveBeenCalled();
-    });
-
-    it("updates the dataset description on success and clears editingDescription", () => {
-      const newDescription = "updated description";
-      component.editingDescription = true;
-      datasetService.updateDatasetDescription.mockReturnValue(of({} as Response));
-
-      component.confirmUpdateDatasetCustomDescription(newDescription);
-
-      expect(datasetService.updateDatasetDescription).toHaveBeenCalledExactlyOnceWith(1, newDescription);
-      expect(component.entry.dataset.description).toBe(newDescription);
-      expect(component.editingDescription).toBe(false);
-    });
-
-    it("notifies the user on error and still clears editingDescription", () => {
-      const originalDescription = component.entry.dataset.description;
-      component.editingDescription = true;
-      datasetService.updateDatasetDescription.mockReturnValue(throwError(() => new Error("boom")));
-
-      component.confirmUpdateDatasetCustomDescription("updated description");
-
-      expect(notificationService.error).toHaveBeenCalledExactlyOnceWith("Update dataset description failed");
-      expect(component.entry.dataset.description).toBe(originalDescription);
-      expect(component.editingDescription).toBe(false);
-    });
-  });
-
-  describe("onClickOpenShareAccess", () => {
-    it("opens the share-access modal with the expected nzData and options", () => {
-      const createSpy = vi.spyOn(modalService, "create").mockReturnValue({} as any);
-
-      component.onClickOpenShareAccess();
-
-      expect(createSpy).toHaveBeenCalledExactlyOnceWith({
-        nzContent: ShareAccessComponent,
-        nzData: {
-          writeAccess: true,
-          type: "dataset",
-          id: 1,
-        },
-        nzFooter: null,
-        nzTitle: "Share this dataset with others",
-        nzCentered: true,
-      });
-    });
-
-    it("sets writeAccess to false when accessPrivilege is not WRITE", () => {
-      fixture.componentInstance.entry = makeEntry({ accessPrivilege: "READ" });
-      fixture.detectChanges();
-      const inner = fixture.componentInstance.inner;
-      const createSpy = vi.spyOn(modalService, "create").mockReturnValue({} as any);
-
-      inner.onClickOpenShareAccess();
-
-      expect(createSpy).toHaveBeenCalledExactlyOnceWith(
-        expect.objectContaining({
-          nzData: expect.objectContaining({ writeAccess: false }),
-        })
-      );
-    });
-  });
-
-  describe("inputs and outputs", () => {
-    it("defaults editable to false", () => {
-      const bare = new UserDatasetListItemComponent(
-        {} as NzModalService,
-        {} as DatasetService,
-        {} as NotificationService
-      );
-      expect(bare.editable).toBe(false);
-    });
-
-    it("exposes deleted, duplicated, and refresh as EventEmitters", () => {
-      expect(component.deleted).toBeInstanceOf(EventEmitter);
-      expect(component.duplicated).toBeInstanceOf(EventEmitter);
-      expect(component.refresh).toBeInstanceOf(EventEmitter);
-    });
-  });
-  /**
-   * Whether this row offers any editing is decided in the template, and by TWO conditions rather
-   * than one: the list must be editable AND the viewer must hold WRITE on the dataset. The suite
-   * above exercises the component's methods and never renders, so neither condition was pinned.
-   */
-  describe("rendered row", () => {
-    /** Re-renders the host with the given entry and list-level editability. */
-    function render(over: Partial<DashboardDataset> = {}, editable = true): HTMLElement {
-      fixture.componentInstance.entry = makeEntry(over);
-      fixture.componentInstance.editable = editable;
-      fixture.detectChanges();
-      component = fixture.componentInstance.inner;
-      return fixture.nativeElement as HTMLElement;
-    }
-
-    /** Titles of every tooltip on the row; interpolated ones never reach the DOM as attributes. */
-    function tooltipTitles(): unknown[] {
-      return fixture.debugElement
-        .queryAll(By.directive(NzTooltipDirective))
-        .map(d => (d.injector.get(NzTooltipDirective) as NzTooltipDirective).directiveTitle);
-    }
-
-    function hasTooltip(pred: (t: string) => boolean): boolean {
-      return tooltipTitles().some(t => typeof t === "string" && pred(t));
-    }
-
-    it("offers the editing controls to a writer on an editable list", () => {
-      render({ accessPrivilege: "WRITE" }, true);
-
-      expect(hasTooltip(t => t === "Customize Dataset Name")).toBe(true);
-      expect(hasTooltip(t => t === "Add Description")).toBe(true);
-    });
-
-    it("withholds them from a reader, even on an editable list", () => {
-      // READ access must not be offered a rename it cannot persist; the list being editable is not
-      // on its own permission to change someone else's dataset.
-      render({ accessPrivilege: "READ" }, true);
-
-      expect(hasTooltip(t => t === "Customize Dataset Name")).toBe(false);
-      expect(hasTooltip(t => t === "Add Description")).toBe(false);
-    });
-
-    it("withholds them on a non-editable list, even from a writer", () => {
-      // Both controls carry the same pair of conditions, so both are asserted: checking only the
-      // rename would let the add-description button lose its `editable` half unnoticed.
-      render({ accessPrivilege: "WRITE" }, false);
-
-      expect(hasTooltip(t => t === "Customize Dataset Name")).toBe(false);
-      expect(hasTooltip(t => t === "Add Description")).toBe(false);
-    });
-
-    it("applies the same pair of conditions to the inline description", () => {
-      render({ accessPrivilege: "READ" }, true);
-
-      (fixture.nativeElement as HTMLElement).querySelector<HTMLElement>(".dataset-description-label")?.click();
-      fixture.detectChanges();
-
-      expect(component.editingDescription).toBe(false);
-    });
-
-    it("keeps the inline description shut on a non-editable list, even for a writer", () => {
-      // The other half of the same `&&`. Without this case the gate could be reduced to the
-      // privilege check alone and every remaining test would still pass.
-      render({ accessPrivilege: "WRITE" }, false);
-
-      (fixture.nativeElement as HTMLElement).querySelector<HTMLElement>(".dataset-description-label")?.click();
-      fixture.detectChanges();
-
-      expect(component.editingDescription).toBe(false);
-    });
-
-    it("opens the inline description for a writer", () => {
-      render({ accessPrivilege: "WRITE" }, true);
-
-      (fixture.nativeElement as HTMLElement).querySelector<HTMLElement>(".dataset-description-label")?.click();
-      fixture.detectChanges();
-
-      expect(component.editingDescription).toBe(true);
-    });
-
-    it("marks a dataset the viewer owns, and only that marker", () => {
-      // The two markers are mutually exclusive; showing both would tell an owner their own dataset
-      // had been shared with them.
-      render({ isOwner: true, accessPrivilege: "WRITE" });
-
-      expect(hasTooltip(t => t === "You are the owner")).toBe(true);
-      expect(hasTooltip(t => t.endsWith(" Access"))).toBe(false);
-    });
-
-    it("tells a non-owner what access they hold instead", () => {
-      // The marker interpolates the privilege, so a reader and a writer are told different things.
-      render({ isOwner: false, accessPrivilege: "READ" });
-
-      expect(hasTooltip(t => t === "You are the owner")).toBe(false);
-      expect(hasTooltip(t => t === "READ Access")).toBe(true);
-    });
-
-    it("swaps the name for an input once renaming starts", () => {
-      const el = render({ accessPrivilege: "WRITE" }, true);
-      expect(el.querySelector("nz-list-item-meta-title input")).toBeNull();
-
-      component.editingName = true;
-      fixture.detectChanges();
-
-      const input = (fixture.nativeElement as HTMLElement).querySelector<HTMLInputElement>(
-        "nz-list-item-meta-title input"
-      )!;
-      expect(input).not.toBeNull();
-      expect(input.value).toBe(component.dataset.name);
-    });
-  });
-});
diff --git a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-list-item/user-dataset-list-item.component.ts b/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-list-item/user-dataset-list-item.component.ts
deleted file mode 100644
index e6e583c4f3..0000000000
--- a/frontend/src/app/dashboard/component/user/user-dataset/user-dataset-list-item/user-dataset-list-item.component.ts
+++ /dev/null
@@ -1,180 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";
-import { Component, EventEmitter, Input, Output } from "@angular/core";
-import { Dataset } from "../../../../../common/type/dataset";
-import { DatasetService, validateDatasetName } from "../../../../service/user/dataset/dataset.service";
-import { ShareAccessComponent } from "../../share-access/share-access.component";
-import { NotificationService } from "../../../../../common/service/notification/notification.service";
-import { extractErrorMessage } from "../../../../../common/util/error";
-import { NzModalService } from "ng-zorro-antd/modal";
-import { DashboardDataset } from "../../../../type/dashboard-dataset.interface";
-import { USER_DATASET } from "../../../../../app-routing.constant";
-import {
-  NzListItemComponent,
-  NzListItemMetaComponent,
-  NzListItemMetaAvatarComponent,
-  NzListItemMetaTitleComponent,
-  NzListItemMetaDescriptionComponent,
-  NzListItemActionsComponent,
-  NzListItemActionComponent,
-} from "ng-zorro-antd/list";
-import { NgStyle, NgIf } from "@angular/common";
-import { NzAvatarComponent } from "ng-zorro-antd/avatar";
-import { RouterLink } from "@angular/router";
-import { NzSpaceCompactItemDirective } from "ng-zorro-antd/space";
-import { NzButtonComponent } from "ng-zorro-antd/button";
-import { ɵNzTransitionPatchDirective } from "ng-zorro-antd/core/transition-patch";
-import { NzTooltipDirective } from "ng-zorro-antd/tooltip";
-import { NzIconDirective } from "ng-zorro-antd/icon";
-import { NzWaveDirective } from "ng-zorro-antd/core/wave";
-import { NzPopconfirmDirective } from "ng-zorro-antd/popconfirm";
-
-@UntilDestroy()
-@Component({
-  selector: "texera-user-dataset-list-item",
-  templateUrl: "./user-dataset-list-item.component.html",
-  styleUrls: ["./user-dataset-list-item.component.scss"],
-  imports: [
-    NzListItemComponent,
-    NzListItemMetaComponent,
-    NzListItemMetaAvatarComponent,
-    NgStyle,
-    NzAvatarComponent,
-    NzListItemMetaTitleComponent,
-    NgIf,
-    RouterLink,
-    NzSpaceCompactItemDirective,
-    NzButtonComponent,
-    ɵNzTransitionPatchDirective,
-    NzTooltipDirective,
-    NzIconDirective,
-    NzListItemMetaDescriptionComponent,
-    NzListItemActionsComponent,
-    NzListItemActionComponent,
-    NzWaveDirective,
-    NzPopconfirmDirective,
-  ],
-})
-export class UserDatasetListItemComponent {
-  protected readonly USER_DATASET = USER_DATASET;
-
-  private _entry?: DashboardDataset;
-
-  @Output()
-  refresh = new EventEmitter<void>();
-
-  @Input()
-  get entry(): DashboardDataset {
-    if (!this._entry) {
-      throw new Error("entry property must be provided to UserDatasetListItemComponent.");
-    }
-    return this._entry;
-  }
-
-  set entry(value: DashboardDataset) {
-    this._entry = value;
-  }
-
-  get dataset(): Dataset {
-    if (!this.entry.dataset) {
-      throw new Error(
-        "Incorrect type of DashboardEntry provided to UserDatasetListItemComponent. Entry must be dataset."
-      );
-    }
-    return this.entry.dataset;
-  }
-
-  @Input() editable = false;
-  @Output() deleted = new EventEmitter<void>();
-  @Output() duplicated = new EventEmitter<void>();
-
-  editingName = false;
-  editingDescription = false;
-
-  constructor(
-    private modalService: NzModalService,
-    private datasetService: DatasetService,
-    private notificationService: NotificationService
-  ) {}
-
-  public confirmUpdateDatasetCustomName(name: string) {
-    if (this.entry.dataset.name === name) {
-      return;
-    }
-
-    const nameError = validateDatasetName(name);
-    if (nameError) {
-      this.notificationService.error(nameError);
-      this.editingName = false;
-      return;
-    }
-
-    if (this.entry.dataset.did)
-      this.datasetService
-        .updateDatasetName(this.entry.dataset.did, name)
-        .pipe(untilDestroyed(this))
-        .subscribe({
-          next: () => {
-            this.entry.dataset.name = name;
-            this.editingName = false;
-          },
-          error: (err: unknown) => {
-            this.notificationService.error(extractErrorMessage(err));
-            this.editingName = false;
-          },
-        });
-  }
-
-  public confirmUpdateDatasetCustomDescription(description: string) {
-    if (this.entry.dataset.description === description) {
-      return;
-    }
-
-    if (this.entry.dataset.did)
-      this.datasetService
-        .updateDatasetDescription(this.entry.dataset.did, description)
-        .pipe(untilDestroyed(this))
-        .subscribe({
-          next: () => {
-            this.entry.dataset.description = description;
-            this.editingDescription = false;
-          },
-          error: () => {
-            this.notificationService.error("Update dataset description failed");
-            this.editingDescription = false;
-          },
-        });
-  }
-
-  public onClickOpenShareAccess() {
-    this.modalService.create({
-      nzContent: ShareAccessComponent,
-      nzData: {
-        writeAccess: this.entry.accessPrivilege === "WRITE",
-        type: "dataset",
-        id: this.dataset.did,
-      },
-      nzFooter: null,
-      nzTitle: "Share this dataset with others",
-      nzCentered: true,
-    });
-  }
-}
diff --git a/frontend/src/app/workspace/service/dynamic-schema/dynamic-schema.service.ts b/frontend/src/app/workspace/service/dynamic-schema/dynamic-schema.service.ts
index 50c33e7e86..9425de4a60 100644
--- a/frontend/src/app/workspace/service/dynamic-schema/dynamic-schema.service.ts
+++ b/frontend/src/app/workspace/service/dynamic-schema/dynamic-schema.service.ts
@@ -102,10 +102,6 @@ export class DynamicSchemaService {
     return this.dynamicSchemaMap;
   }
 
-  public dynamicSchemaExists(operatorID: string): boolean {
-    return this.dynamicSchemaMap.has(operatorID);
-  }
-
   /**
    * Based on the operatorID, get the current dynamic operator schema that is created through autocomplete
    */
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 e73f28b39a..7842661761 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
@@ -148,57 +148,6 @@ describe("WorkflowResultService", () => {
     expect(service.hasPaginatedResult("op")).toBe(false);
   });
 
-  it("handleCleanResultCache drops operators no longer available and resets invalidated caches", () => {
-    const ws = TestBed.inject(WorkflowWebsocketService);
-    pushWsEvent(ws, {
-      type: "WebResultUpdateEvent",
-      updates: {
-        goneData: snapshotUpdate([{ a: 1 }]),
-        gonePag: paginationUpdate(3),
-        resetData: snapshotUpdate([{ keep: 1 }]),
-      },
-      tableStats: {},
-    });
-    expect(service.getResultService("resetData")!.getCurrentResultSnapshot()).toEqual([{ keep: 1 }]);
-
-    pushWsEvent(ws, {
-      type: "WorkflowAvailableResultEvent",
-      availableOperators: {
-        keepPag: { cacheValid: true, outputMode: { type: "PaginationMode" } },
-        resetData: { cacheValid: false, outputMode: { type: "SetSnapshotMode" } },
-      },
-    });
-
-    // operators absent from the available set are dropped from both caches
-    expect(service.hasResult("goneData")).toBe(false);
-    expect(service.hasPaginatedResult("gonePag")).toBe(false);
-    // a freshly-available operator gets a new (paginated) service
-    expect(service.hasPaginatedResult("keepPag")).toBe(true);
-    // an available-but-invalidated operator keeps its service but has its cache reset
-    expect(service.hasResult("resetData")).toBe(true);
-    expect(service.getResultService("resetData")!.getCurrentResultSnapshot()).toBeUndefined();
-  });
-
-  it("handleCleanResultCache reports removed and invalidated operators on the result-update stream", () => {
-    const ws = TestBed.inject(WorkflowWebsocketService);
-    pushWsEvent(ws, {
-      type: "WebResultUpdateEvent",
-      updates: { goneData: snapshotUpdate([{ a: 1 }]) },
-      tableStats: {},
-    });
-
-    const updateEvents: Record<string, unknown>[] = [];
-    service.getResultUpdateStream().subscribe(u => updateEvents.push(u));
-
-    pushWsEvent(ws, {
-      type: "WorkflowAvailableResultEvent",
-      availableOperators: { resetPag: { cacheValid: false, outputMode: { type: "PaginationMode" } } },
-    });
-
-    expect(updateEvents.length).toBe(1);
-    expect(updateEvents[0]).toEqual({ goneData: undefined, resetPag: undefined });
-  });
-
   it("determineOutputTypes distinguishes binary from non-binary paginated output", () => {
     const ws = TestBed.inject(WorkflowWebsocketService);
     pushWsEvent(ws, {
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 26133a636e..89d4e453fa 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
@@ -28,7 +28,7 @@ import {
   WorkflowResultUpdate,
 } from "../../types/execute-workflow.interface";
 import { WorkflowWebsocketService } from "../workflow-websocket/workflow-websocket.service";
-import { PaginatedResultEvent, WorkflowAvailableResultEvent } from "../../types/workflow-websocket.interface";
+import { PaginatedResultEvent } from "../../types/workflow-websocket.interface";
 import { map, Observable, of, pairwise, ReplaySubject, Subject } from "rxjs";
 import { v4 as uuid } from "uuid";
 import { IndexableObject } from "../../types/result-table.interface";
@@ -57,9 +57,6 @@ export class WorkflowResultService {
       this.handleResultUpdate(event.updates);
       this.handleTableStatsUpdate(event.tableStats);
     });
-    this.wsService
-      .subscribeToEvent("WorkflowAvailableResultEvent")
-      .subscribe(event => this.handleCleanResultCache(event));
     this.resultTableStats.next({});
   }
 
@@ -117,48 +114,6 @@ export class WorkflowResultService {
     this.resultClearedStream.next();
   }
 
-  private handleCleanResultCache(event: WorkflowAvailableResultEvent): void {
-    const removedOrInvalidatedOperators = new Set<string>();
-    // remove operators that no longer have results
-    this.operatorResultServices.forEach((_, op) => {
-      if (!(op in event.availableOperators)) {
-        this.operatorResultServices.delete(op);
-        removedOrInvalidatedOperators.add(op);
-      }
-    });
-    this.paginatedResultServices.forEach((_, op) => {
-      if (!(op in event.availableOperators)) {
-        this.paginatedResultServices.delete(op);
-        removedOrInvalidatedOperators.add(op);
-      }
-    });
-    // for each operator that has results:
-    Object.entries(event.availableOperators).forEach(availableOp => {
-      const op = availableOp[0];
-      const cacheValid = availableOp[1].cacheValid;
-      const outputMode = availableOp[1].outputMode;
-
-      // make sure to init or reuse result service for each operator
-      const resultService = (() => {
-        if (outputMode.type === "PaginationMode") {
-          return this.getOrInitPaginatedResultService(op);
-        } else {
-          return this.getOrInitResultService(op);
-        }
-      })();
-
-      // invalidate frontend cache if needed
-      if (!cacheValid) {
-        resultService.reset();
-        removedOrInvalidatedOperators.add(op);
-      }
-    });
-
-    const invalidatedOperatorsUpdate: Record<string, undefined> = {};
-    removedOrInvalidatedOperators.forEach(op => (invalidatedOperatorsUpdate[op] = undefined));
-    this.resultUpdateStream.next(invalidatedOperatorsUpdate);
-  }
-
   private handleResultUpdate(event: WorkflowResultUpdate): void {
     Object.keys(event).forEach(operatorID => {
       const update = event[operatorID];
diff --git a/frontend/src/app/workspace/types/workflow-websocket.interface.ts b/frontend/src/app/workspace/types/workflow-websocket.interface.ts
index afd5ea6f04..475a9a2734 100644
--- a/frontend/src/app/workspace/types/workflow-websocket.interface.ts
+++ b/frontend/src/app/workspace/types/workflow-websocket.interface.ts
@@ -22,7 +22,6 @@ import {
   LogicalOperator,
   LogicalPlan,
   OperatorStatsUpdate,
-  WebOutputMode,
   WorkflowResultUpdateEvent,
 } from "./execute-workflow.interface";
 import { IndexableObject } from "./result-table.interface";
@@ -124,16 +123,6 @@ export type ResultExportResponse = Readonly<{
   message: string;
 }>;
 
-export type OperatorAvailableResult = Readonly<{
-  operatorID: string;
-  cacheValid: boolean;
-  outputMode: WebOutputMode;
-}>;
-
-export type WorkflowAvailableResultEvent = Readonly<{
-  availableOperators: ReadonlyArray<OperatorAvailableResult>;
-}>;
-
 export type OperatorResultCacheStatus = "cache invalid" | "cache valid";
 
 export interface CacheStatusUpdateEvent
@@ -233,7 +222,6 @@ export type TexeraWebsocketEventTypeMap = {
   OperatorCurrentTuplesUpdateEvent: OperatorCurrentTuples;
   PaginatedResultEvent: PaginatedResultEvent;
   ResultExportResponse: ResultExportResponse;
-  WorkflowAvailableResultEvent: WorkflowAvailableResultEvent;
   CacheStatusUpdateEvent: CacheStatusUpdateEvent;
   PythonExpressionEvaluateResponse: PythonExpressionEvaluateResponse;
   WorkerAssignmentUpdateEvent: WorkerAssignmentUpdateEvent;