chore: Remove socket-io and websocket connections (#37784)

We don't use the websocket connection for anything of consequence. This
PR removes it and the `socket-io` dependency from the client.

The RTS still has it, will be removed in a subsequent PR.

## Automation

/test sanity

### 🔍 Cypress test results
<!-- This is an auto-generated comment: Cypress test results  -->
> [!TIP]
> 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉
> Workflow run:
<https://github.com/appsmithorg/appsmith/actions/runs/12062399334>
> Commit: 4f018b1958e82ca29d8a7492ec0bf4529f43b0ef
> <a
href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=12062399334&attempt=1"
target="_blank">Cypress dashboard</a>.
> Tags: `@tag.Sanity`
> Spec:
> <hr>Thu, 28 Nov 2024 04:55:02 UTC
<!-- end of auto-generated comment: Cypress test results  -->


## Communication
Should the DevRel and Marketing teams inform users about this change?
- [ ] Yes
- [x] No


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

## Release Notes

- **New Features**
	- None

- **Bug Fixes**
	- None

- **Refactor**
- Removed websocket and collaborative editing functionality, simplifying
the application architecture.
- Eliminated related constants, actions, reducers, and sagas to
streamline codebase.

- **Chores**
- Updated test configurations by removing references to websocket sagas.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Shrikant Sharat Kandula 2024-11-28 10:58:56 +05:30 committed by GitHub
parent 0f3593af24
commit a1c8cb69f0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 1 additions and 707 deletions

View File

@ -218,7 +218,6 @@
"showdown": "^1.9.1",
"simplebar-react": "^2.4.3",
"smartlook-client": "^8.0.0",
"socket.io-client": "^4.5.4",
"sql-formatter": "12.2.0",
"styled-components": "^5.3.6",
"tailwindcss": "^3.3.3",

View File

@ -1,78 +0,0 @@
import {
appLevelWebsocketWriteEvent,
pageLevelWebsocketWriteEvent,
} from "./websocketActions";
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
import { PAGE_LEVEL_SOCKET_EVENTS } from "sagas/WebsocketSagas/socketEvents";
// App Editors presence Socket actions
export const collabStartEditingAppEvent = (appId: string) =>
appLevelWebsocketWriteEvent({
type: PAGE_LEVEL_SOCKET_EVENTS.START_EDITING_APP,
payload: appId,
});
export const collabStopEditingAppEvent = (appId: string) =>
appLevelWebsocketWriteEvent({
type: PAGE_LEVEL_SOCKET_EVENTS.STOP_EDITING_APP,
payload: appId,
});
// App Editor presence Redux actions
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const collabSetAppEditors = (payload: any) => ({
type: ReduxActionTypes.APP_COLLAB_LIST_EDITORS,
payload,
});
export const collabResetAppEditors = () => ({
type: ReduxActionTypes.APP_COLLAB_RESET_EDITORS,
});
// Pointer Sharing Socket Events
export const collabStartSharingPointerEvent = (pageId: string) =>
pageLevelWebsocketWriteEvent({
type: PAGE_LEVEL_SOCKET_EVENTS.START_EDITING_APP,
payload: pageId,
});
export const collabStopSharingPointerEvent = (pageId?: string) =>
pageLevelWebsocketWriteEvent({
type: PAGE_LEVEL_SOCKET_EVENTS.STOP_EDITING_APP,
payload: pageId,
});
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const collabShareUserPointerEvent = (payload: any) =>
pageLevelWebsocketWriteEvent({
type: PAGE_LEVEL_SOCKET_EVENTS.SHARE_USER_POINTER,
payload,
});
// Pointer Sharing Redux actions
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const collabSetEditorsPointersData = (payload: any) => ({
type: ReduxActionTypes.APP_COLLAB_SET_EDITORS_POINTER_DATA,
payload,
});
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const collabUnsetEditorsPointersData = (payload: any) => ({
type: ReduxActionTypes.APP_COLLAB_UNSET_EDITORS_POINTER_DATA,
payload,
});
export const collabResetEditorsPointersData = () => ({
type: ReduxActionTypes.APP_COLLAB_RESET_EDITORS_POINTER_DATA,
});
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const collabConcurrentPageEditorsData = (payload: any) => ({
type: ReduxActionTypes.APP_COLLAB_SET_CONCURRENT_PAGE_EDITORS,
payload,
});

View File

@ -1,8 +0,0 @@
import { appLevelWebsocketWriteEvent } from "./websocketActions";
import { APP_LEVEL_SOCKET_EVENTS } from "sagas/WebsocketSagas/socketEvents";
export const pageVisibilityAppEvent = (visibility: DocumentVisibilityState) =>
appLevelWebsocketWriteEvent({
type: APP_LEVEL_SOCKET_EVENTS.PAGE_VISIBILITY,
payload: visibility,
});

View File

@ -1,44 +0,0 @@
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
import { reconnectWebsocketEvent } from "constants/WebsocketConstants";
export const setIsAppLevelWebsocketConnected = (payload: boolean) => ({
type: ReduxActionTypes.SET_IS_APP_LEVEL_WEBSOCKET_CONNECTED,
payload,
});
export const setIsPageLevelWebsocketConnected = (payload: boolean) => ({
type: ReduxActionTypes.SET_IS_PAGE_LEVEL_WEBSOCKET_CONNECTED,
payload,
});
export const appLevelWebsocketWriteEvent = (payload: {
type: string;
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
payload?: any;
}) => ({
type: ReduxActionTypes.WEBSOCKET_APP_LEVEL_WRITE_CHANNEL,
payload,
});
export const pageLevelWebsocketWriteEvent = (payload: {
type: string;
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
payload?: any;
}) => ({
type: ReduxActionTypes.WEBSOCKET_PAGE_LEVEL_WRITE_CHANNEL,
payload,
});
export const reconnectAppLevelWebsocket = () =>
appLevelWebsocketWriteEvent(reconnectWebsocketEvent());
export const initAppLevelSocketConnection = () => ({
type: ReduxActionTypes.INIT_APP_LEVEL_SOCKET_CONNECTION,
});
export const reconnectPageLevelWebsocket = () =>
pageLevelWebsocketWriteEvent(reconnectWebsocketEvent());
export const initPageLevelSocketConnection = () => ({
type: ReduxActionTypes.INIT_PAGE_LEVEL_SOCKET_CONNECTION,
});

View File

@ -1,16 +1,6 @@
import type { ERROR_CODES } from "ee/constants/ApiConstants";
import type { AffectedJSObjects } from "sagas/EvaluationsSagaUtils";
const WebsocketActions = {
WEBSOCKET_APP_LEVEL_WRITE_CHANNEL: "WEBSOCKET_APP_LEVEL_WRITE_CHANNEL",
WEBSOCKET_PAGE_LEVEL_WRITE_CHANNEL: "WEBSOCKET_PAGE_LEVEL_WRITE_CHANNEL",
INIT_APP_LEVEL_SOCKET_CONNECTION: "INIT_APP_LEVEL_SOCKET_CONNECTION",
INIT_PAGE_LEVEL_SOCKET_CONNECTION: "INIT_PAGE_LEVEL_SOCKET_CONNECTION",
SET_IS_APP_LEVEL_WEBSOCKET_CONNECTED: "SET_IS_APP_LEVEL_WEBSOCKET_CONNECTED",
SET_IS_PAGE_LEVEL_WEBSOCKET_CONNECTED:
"SET_IS_PAGE_LEVEL_WEBSOCKET_CONNECTED",
};
const ActionSelectorReduxActionTypes = {
EVALUATE_ACTION_SELECTOR_FIELD: "EVALUATE_ACTION_SELECTOR_FIELD",
SET_EVALUATED_ACTION_SELECTOR_FIELD: "SET_EVALUATED_ACTION_SELECTOR_FIELD",
@ -307,18 +297,6 @@ const EvaluationActionErrorTypes = {
FAILED_CORRECTING_BINDING_PATHS: "FAILED_CORRECTING_BINDING_PATHS",
};
const AppCollabActionTypes = {
APP_COLLAB_SET_CONCURRENT_PAGE_EDITORS:
"APP_COLLAB_SET_CONCURRENT_PAGE_EDITORS",
APP_COLLAB_LIST_EDITORS: "APP_COLLAB_LIST_EDITORS",
APP_COLLAB_RESET_EDITORS: "APP_COLLAB_RESET_EDITORS",
APP_COLLAB_SET_EDITORS_POINTER_DATA: "APP_COLLAB_SET_EDITORS_POINTER_DATA",
APP_COLLAB_UNSET_EDITORS_POINTER_DATA:
"APP_COLLAB_UNSET_EDITORS_POINTER_DATA",
APP_COLLAB_RESET_EDITORS_POINTER_DATA:
"APP_COLLAB_RESET_EDITORS_POINTER_DATA",
};
const OmniSearchActionTypes = {
SET_SEARCH_FILTER_CONTEXT: "SET_SEARCH_FILTER_CONTEXT",
SET_GLOBAL_SEARCH_QUERY: "SET_GLOBAL_SEARCH_QUERY",
@ -1280,7 +1258,6 @@ export const ReduxActionTypes = {
...AdminSettingsActionTypes,
...AnalyticsActionTypes,
...AIActionTypes,
...AppCollabActionTypes,
...ApplicationActionTypes,
...AppThemeActionsTypes,
...AppViewActionTypes,
@ -1316,7 +1293,6 @@ export const ReduxActionTypes = {
...ThemeActionTypes,
...UserAuthActionTypes,
...UserProfileActionTypes,
...WebsocketActions,
...WidgetCanvasActionTypes,
...WidgetOperationsActionTypes,
...WorkspaceActionTypes,

View File

@ -36,7 +36,6 @@ import type { GlobalSearchReduxState } from "reducers/uiReducers/globalSearchRed
import type { ActionSelectorReduxState } from "reducers/uiReducers/actionSelectorReducer";
import type { ReleasesState } from "reducers/uiReducers/releasesReducer";
import type { LoadingEntitiesState } from "reducers/evaluationReducers/loadingEntitiesReducer";
import type { WebsocketReducerState } from "reducers/uiReducers/websocketReducer";
import type { DebuggerReduxState } from "reducers/uiReducers/debuggerReducer";
import type { TourReducerState } from "reducers/uiReducers/tourReducer";
import type { TableFilterPaneReduxState } from "reducers/uiReducers/tableFilterPaneReducer";
@ -45,7 +44,6 @@ import type { JSCollectionDataState } from "ee/reducers/entityReducers/jsActions
import type { CanvasSelectionState } from "reducers/uiReducers/canvasSelectionReducer";
import type { JSObjectNameReduxState } from "reducers/uiReducers/jsObjectNameReducer";
import type { GitSyncReducerState } from "reducers/uiReducers/gitSyncReducer";
import type { AppCollabReducerState } from "reducers/uiReducers/appCollabReducer";
import type { CrudInfoModalReduxState } from "reducers/uiReducers/crudInfoModalReducer";
import type { FormEvaluationState } from "reducers/evaluationReducers/formEvaluationReducer";
import type { widgetReflow } from "reducers/uiReducers/reflowReducer";
@ -121,14 +119,12 @@ export interface AppState {
onBoarding: OnboardingState;
globalSearch: GlobalSearchReduxState;
releases: ReleasesState;
websocket: WebsocketReducerState;
debugger: DebuggerReduxState;
tour: TourReducerState;
jsPane: JsPaneReduxState;
canvasSelection: CanvasSelectionState;
jsObjectName: JSObjectNameReduxState;
gitSync: GitSyncReducerState;
appCollab: AppCollabReducerState;
crudInfoModal: CrudInfoModalReduxState;
widgetReflow: widgetReflow;
appTheming: AppThemingState;

View File

@ -23,12 +23,10 @@ import onBoardingReducer from "reducers/uiReducers/onBoardingReducer";
import globalSearchReducer from "reducers/uiReducers/globalSearchReducer";
import actionSelectorReducer from "reducers/uiReducers/actionSelectorReducer";
import releasesReducer from "reducers/uiReducers/releasesReducer";
import websocketReducer from "reducers/uiReducers/websocketReducer";
import debuggerReducer from "reducers/uiReducers/debuggerReducer";
import tourReducer from "reducers/uiReducers/tourReducer";
import tableFilterPaneReducer from "reducers/uiReducers/tableFilterPaneReducer";
import jsPaneReducer from "reducers/uiReducers/jsPaneReducer";
import appCollabReducer from "reducers/uiReducers/appCollabReducer";
import canvasSelectionReducer from "reducers/uiReducers/canvasSelectionReducer";
import gitSyncReducer from "reducers/uiReducers/gitSyncReducer";
import crudInfoModalReducer from "reducers/uiReducers/crudInfoModalReducer";
@ -78,14 +76,12 @@ export const uiReducerObject = {
onBoarding: onBoardingReducer,
globalSearch: globalSearchReducer,
releases: releasesReducer,
websocket: websocketReducer,
debugger: debuggerReducer,
tour: tourReducer,
jsPane: jsPaneReducer,
jsObjectName: jsObjectNameReducer,
canvasSelection: canvasSelectionReducer,
gitSync: gitSyncReducer,
appCollab: appCollabReducer,
crudInfoModal: crudInfoModalReducer,
widgetReflow: widgetReflowReducer,
appTheming: appThemingReducer,

View File

@ -73,10 +73,6 @@ import {
deleteRecentAppEntities,
getEnableStartSignposting,
} from "utils/storage";
import {
reconnectAppLevelWebsocket,
reconnectPageLevelWebsocket,
} from "actions/websocketActions";
import { getFetchedWorkspaces } from "ee/selectors/workspaceSelectors";
import { fetchPluginFormConfigs, fetchPlugins } from "actions/pluginActions";
@ -648,12 +644,6 @@ export function* createApplicationSaga(
basePageId: defaultPage?.baseId,
}),
);
// subscribe to newly created application
// users join rooms on connection, so reconnecting
// ensures user receives the updates in the app just created
yield put(reconnectAppLevelWebsocket());
yield put(reconnectPageLevelWebsocket());
}
}
} catch (error) {

View File

@ -33,7 +33,6 @@ import LintingSaga from "sagas/LintingSagas";
import modalSagas from "sagas/ModalSagas";
import onboardingSagas from "sagas/OnboardingSagas";
import pageSagas from "ee/sagas/PageSagas";
import PageVisibilitySaga from "sagas/PageVisibilitySagas";
import pluginSagas from "sagas/PluginSagas";
import queryPaneSagas from "sagas/QueryPaneSagas";
import replaySaga from "sagas/ReplaySaga";
@ -42,7 +41,6 @@ import snapshotSagas from "sagas/SnapshotSagas";
import snipingModeSagas from "sagas/SnipingModeSagas";
import templateSagas from "sagas/TemplatesSagas";
import themeSagas from "sagas/ThemeSaga";
import websocketSagas from "sagas/WebsocketSagas/WebsocketSagas";
import actionExecutionChangeListeners from "sagas/WidgetLoadingSaga";
import widgetOperationSagas from "sagas/WidgetOperationSagas";
import oneClickBindingSaga from "sagas/OneClickBindingSaga";
@ -83,7 +81,6 @@ export const sagas = [
actionExecutionChangeListeners,
formEvaluationChangeListener,
globalSearchSagas,
websocketSagas,
debuggerSagas,
saaSPaneSagas,
selectionCanvasSagas,
@ -94,7 +91,6 @@ export const sagas = [
appThemingSaga,
NavigationSagas,
editorContextSagas,
PageVisibilitySaga,
AutoHeightSagas,
tenantSagas,
JSLibrarySaga,

View File

@ -52,10 +52,6 @@ import {
getCurrentUser,
getFeatureFlagsFetched,
} from "selectors/usersSelectors";
import {
initAppLevelSocketConnection,
initPageLevelSocketConnection,
} from "actions/websocketActions";
import {
getEnableStartSignposting,
getFirstTimeUserOnboardingApplicationIds,
@ -181,9 +177,6 @@ export function* runUserSideEffectsSaga() {
);
}
yield put(initAppLevelSocketConnection());
yield put(initPageLevelSocketConnection());
if (currentUser.emptyInstance) {
history.replace(SETUP);
}

View File

@ -1,22 +0,0 @@
export const WEBSOCKET_EVENTS = {
RECONNECT: "RECONNECT",
DISCONNECTED: "DISCONNECTED",
CONNECTED: "CONNECTED",
};
export const reconnectWebsocketEvent = () => ({
type: WEBSOCKET_EVENTS.RECONNECT,
});
export const websocketDisconnectedEvent = () => ({
type: WEBSOCKET_EVENTS.DISCONNECTED,
});
export const websocketConnectedEvent = () => ({
type: WEBSOCKET_EVENTS.CONNECTED,
});
export const RTS_BASE_PATH = "/rts";
export const WEBSOCKET_NAMESPACE = {
PAGE_EDIT: "/page/edit",
};

View File

@ -403,7 +403,6 @@ export const DEDICATED_WORKER_GLOBAL_SCOPE_IDENTIFIERS = {
webkitRequestFileSystemSync: "webkitRequestFileSystemSync",
webkitResolveLocalFileSystemSyncURL: "webkitResolveLocalFileSystemSyncURL",
webkitResolveLocalFileSystemURL: "webkitResolveLocalFileSystemURL",
WebSocket: "WebSocket",
WebTransport: "WebTransport",
WebTransportBidirectionalStream: "WebTransportBidirectionalStream",
WebTransportDatagramDuplexStream: "WebTransportDatagramDuplexStream",

View File

@ -1,87 +0,0 @@
import type { ReduxAction } from "ee/constants/ReduxActionConstants";
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
import { createReducer } from "utils/ReducerUtils";
import type { User } from "entities/AppCollab/CollabInterfaces";
import { cloneDeep } from "lodash";
const initialState: AppCollabReducerState = {
editors: [],
pointerData: {},
pageEditors: [],
};
const appCollabReducer = createReducer(initialState, {
[ReduxActionTypes.APP_COLLAB_LIST_EDITORS]: (
state: AppCollabReducerState,
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
action: ReduxAction<any>,
) => {
return { ...state, editors: action.payload.users };
},
[ReduxActionTypes.APP_COLLAB_RESET_EDITORS]: (
state: AppCollabReducerState,
) => {
return { ...state, editors: [] };
},
[ReduxActionTypes.APP_COLLAB_SET_EDITORS_POINTER_DATA]: (
state: AppCollabReducerState,
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
action: ReduxAction<any>,
) => {
return {
...state,
pointerData: {
...state.pointerData,
[action.payload.socketId]: action.payload,
},
};
},
[ReduxActionTypes.APP_COLLAB_UNSET_EDITORS_POINTER_DATA]: (
state: AppCollabReducerState,
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
action: ReduxAction<any>,
) => {
const clonedPointerData = cloneDeep(state.pointerData);
delete clonedPointerData[action.payload];
return {
...state,
clonedPointerData,
};
},
[ReduxActionTypes.APP_COLLAB_RESET_EDITORS_POINTER_DATA]: (
state: AppCollabReducerState,
) => {
return {
...state,
pointerData: {},
};
},
[ReduxActionTypes.APP_COLLAB_SET_CONCURRENT_PAGE_EDITORS]: (
state: AppCollabReducerState,
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
action: ReduxAction<any>,
) => ({
...state,
pageEditors: action.payload,
}),
});
interface PointerDataType {
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[s: string]: any;
}
export interface AppCollabReducerState {
editors: User[];
pointerData: PointerDataType;
pageEditors: User[];
}
export default appCollabReducer;

View File

@ -1,30 +0,0 @@
import { createReducer } from "utils/ReducerUtils";
import type { ReduxAction } from "ee/constants/ReduxActionConstants";
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
const initialState: WebsocketReducerState = {
appLevelSocketConnected: false,
pageLevelSocketConnected: false,
};
const websocketReducer = createReducer(initialState, {
[ReduxActionTypes.SET_IS_APP_LEVEL_WEBSOCKET_CONNECTED]: (
state: WebsocketReducerState,
action: ReduxAction<boolean>,
) => {
return { ...state, appLevelSocketConnected: action.payload };
},
[ReduxActionTypes.SET_IS_PAGE_LEVEL_WEBSOCKET_CONNECTED]: (
state: WebsocketReducerState,
action: ReduxAction<boolean>,
) => {
return { ...state, pageLevelSocketConnected: action.payload };
},
});
export interface WebsocketReducerState {
appLevelSocketConnected: boolean;
pageLevelSocketConnected: boolean;
}
export default websocketReducer;

View File

@ -1,35 +0,0 @@
import type { EventChannel } from "redux-saga";
import { eventChannel } from "redux-saga";
import { call, fork, put, take } from "redux-saga/effects";
import { pageVisibilityAppEvent } from "actions/pageVisibilityActions";
// Track page visibility
// https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
function listenToVisibilityEvents() {
return eventChannel((emitter) => {
document.addEventListener("visibilitychange", emitter, false);
return () => {
document.removeEventListener("visibilitychange", emitter, false);
};
});
}
function* handleTabVisibilityConnection() {
const channel: EventChannel<unknown> = yield call(listenToVisibilityEvents);
while (true) {
const event: {
target: { visibilityState: DocumentVisibilityState };
} = yield take(channel);
// Only invoke when page gets visible
if (event.target && event.target.visibilityState === "visible") {
yield put(pageVisibilityAppEvent(event.target.visibilityState));
}
}
}
export default function* rootSaga() {
yield fork(handleTabVisibilityConnection);
}

View File

@ -1,214 +0,0 @@
import type { Socket, ManagerOptions, SocketOptions } from "socket.io-client";
import { io } from "socket.io-client";
import type { EventChannel, Task } from "redux-saga";
import { eventChannel } from "redux-saga";
import { fork, take, call, cancel, put } from "redux-saga/effects";
import { ReduxActionTypes } from "ee/constants/ReduxActionConstants";
import {
WEBSOCKET_EVENTS,
RTS_BASE_PATH,
WEBSOCKET_NAMESPACE,
websocketDisconnectedEvent,
websocketConnectedEvent,
} from "constants/WebsocketConstants";
import {
setIsAppLevelWebsocketConnected,
setIsPageLevelWebsocketConnected,
} from "actions/websocketActions";
import handleAppLevelSocketEvents from "./handleAppLevelSocketEvents";
import handlePageLevelSocketEvents from "./handlePageLevelSocketEvents";
import * as Sentry from "@sentry/react";
import { SOCKET_CONNECTION_EVENTS } from "./socketEvents";
async function connect(namespace?: string) {
const options: Partial<ManagerOptions & SocketOptions> = {
path: RTS_BASE_PATH,
// The default transports is ["polling", "websocket"], so polling is tried first. But polling
// needs sticky session to be turned on, in a clustered environment, even for it to upgrade to websockets.
// Ref: <https://github.com/socketio/socket.io/issues/2140>.
transports: ["websocket"],
reconnectionAttempts: 5,
reconnectionDelay: 3000,
};
const socket = !!namespace ? io(namespace, options) : io(options);
return new Promise((resolve) => {
socket.on(SOCKET_CONNECTION_EVENTS.CONNECT, () => {
socket.off(SOCKET_CONNECTION_EVENTS.CONNECT);
resolve(socket);
});
});
}
function listenToSocket(socket: Socket) {
return eventChannel((emit) => {
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
socket.onAny((event: any, ...args: any) => {
emit({
type: event,
payload: args,
});
});
socket.on(SOCKET_CONNECTION_EVENTS.DISCONNECT, () => {
emit(websocketDisconnectedEvent());
});
socket.on(SOCKET_CONNECTION_EVENTS.CONNECT, () => {
emit(websocketConnectedEvent());
});
return () => {
socket.disconnect();
};
});
}
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function* readFromAppSocket(socket: any) {
const channel: EventChannel<unknown> = yield call(listenToSocket, socket);
while (true) {
const action: { type: keyof typeof WEBSOCKET_EVENTS } = yield take(channel);
switch (action.type) {
case WEBSOCKET_EVENTS.DISCONNECTED:
yield put(setIsAppLevelWebsocketConnected(false));
break;
case WEBSOCKET_EVENTS.CONNECTED:
yield put(setIsAppLevelWebsocketConnected(true));
break;
default: {
yield call(handleAppLevelSocketEvents, action);
}
}
}
}
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function* writeToAppSocket(socket: any) {
while (true) {
const { payload } = yield take(
ReduxActionTypes.WEBSOCKET_APP_LEVEL_WRITE_CHANNEL,
);
// reconnect to reset connection at the server
try {
if (payload.type === WEBSOCKET_EVENTS.RECONNECT) {
yield put(setIsAppLevelWebsocketConnected(false));
socket.disconnect().connect();
} else {
socket.emit(payload.type, payload.payload);
}
} catch (e) {
Sentry.captureException(e);
}
}
}
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function* handleAppSocketIO(socket: any) {
yield fork(readFromAppSocket, socket);
yield fork(writeToAppSocket, socket);
}
function* openAppLevelSocketConnection() {
while (true) {
yield take(ReduxActionTypes.INIT_APP_LEVEL_SOCKET_CONNECTION);
try {
/**
* Incase the socket is disconnected due to network latencies
* it reuses the same instance so we don't need to bind it again
* this is verified using the reconnect flow
* We only need to retry incase the socket connection isn't made
* in the first attempt itself
*/
const socket: Socket = yield call(connect);
const task: Task = yield fork(handleAppSocketIO, socket);
yield put(setIsAppLevelWebsocketConnected(true));
yield take([ReduxActionTypes.LOGOUT_USER_INIT]);
yield cancel(task);
socket?.disconnect();
} catch (e) {
Sentry.captureException(e);
}
}
}
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function* readFromPageSocket(socket: any) {
const channel: EventChannel<unknown> = yield call(listenToSocket, socket);
while (true) {
const action: { type: keyof typeof WEBSOCKET_EVENTS } = yield take(channel);
switch (action.type) {
case WEBSOCKET_EVENTS.DISCONNECTED:
yield put(setIsPageLevelWebsocketConnected(false));
break;
case WEBSOCKET_EVENTS.CONNECTED:
yield put(setIsPageLevelWebsocketConnected(true));
break;
default: {
yield call(handlePageLevelSocketEvents, action, socket);
}
}
}
}
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function* writeToPageSocket(socket: any) {
while (true) {
const { payload } = yield take(
ReduxActionTypes.WEBSOCKET_PAGE_LEVEL_WRITE_CHANNEL,
);
// reconnect to reset connection at the server
try {
if (payload.type === WEBSOCKET_EVENTS.RECONNECT) {
yield put(setIsPageLevelWebsocketConnected(false));
socket.disconnect().connect();
} else {
socket.emit(payload.type, payload.payload);
}
} catch (e) {
Sentry.captureException(e);
}
}
}
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function* handlePageSocketIO(socket: any) {
yield fork(readFromPageSocket, socket);
yield fork(writeToPageSocket, socket);
}
function* openPageLevelSocketConnection() {
while (true) {
yield take(ReduxActionTypes.INIT_PAGE_LEVEL_SOCKET_CONNECTION);
try {
const socket: Socket = yield call(connect, WEBSOCKET_NAMESPACE.PAGE_EDIT);
const task: Task = yield fork(handlePageSocketIO, socket);
yield put(setIsPageLevelWebsocketConnected(true));
yield take([ReduxActionTypes.LOGOUT_USER_INIT]);
yield cancel(task);
socket.disconnect();
} catch (e) {
Sentry.captureException(e);
}
}
}
export default function* rootSaga() {
yield fork(openAppLevelSocketConnection);
yield fork(openPageLevelSocketConnection);
}

View File

@ -1,17 +0,0 @@
import { put } from "redux-saga/effects";
import { APP_LEVEL_SOCKET_EVENTS } from "./socketEvents";
import { collabSetAppEditors } from "actions/appCollabActions";
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export default function* handleAppLevelSocketEvents(event: any) {
switch (event.type) {
// Collab V2 - Realtime Editing
case APP_LEVEL_SOCKET_EVENTS.LIST_ONLINE_APP_EDITORS: {
yield put(collabSetAppEditors(event.payload[0]));
return;
}
}
}

View File

@ -1,37 +0,0 @@
import { put } from "redux-saga/effects";
import { PAGE_LEVEL_SOCKET_EVENTS } from "./socketEvents";
import {
collabSetEditorsPointersData,
collabUnsetEditorsPointersData,
collabConcurrentPageEditorsData,
} from "actions/appCollabActions";
import * as Sentry from "@sentry/react";
// TODO: Fix this the next time the file is edited
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export default function* handlePageLevelSocketEvents(event: any, socket: any) {
try {
switch (event.type) {
case PAGE_LEVEL_SOCKET_EVENTS.SHARE_USER_POINTER: {
if (socket.id !== event.payload[0].socketId) {
yield put(collabSetEditorsPointersData(event.payload[0]));
}
return;
}
case PAGE_LEVEL_SOCKET_EVENTS.STOP_EDITING_APP: {
yield put(collabUnsetEditorsPointersData(event.payload[0]));
return;
}
case PAGE_LEVEL_SOCKET_EVENTS.LIST_ONLINE_PAGE_EDITORS: {
yield put(collabConcurrentPageEditorsData(event.payload[0]?.users));
return;
}
}
} catch (e) {
Sentry.captureException(e);
}
}

View File

@ -1,22 +0,0 @@
export const SOCKET_CONNECTION_EVENTS = {
CONNECT: "connect",
DISCONNECT: "disconnect",
};
export const APP_LEVEL_SOCKET_EVENTS = {
// notification events
INSERT_NOTIFICATION: "insert:notification",
LIST_ONLINE_APP_EDITORS: "collab:online_editors", // user presence
RELEASE_VERSION_NOTIFICATION: "info:release_version", // release version
PAGE_VISIBILITY: "info:page_visibility", // is the page/tab visible to the user
};
export const PAGE_LEVEL_SOCKET_EVENTS = {
START_EDITING_APP: "collab:start_edit",
STOP_EDITING_APP: "collab:leave_edit",
LIST_ONLINE_PAGE_EDITORS: "collab:online_editors",
SHARE_USER_POINTER: "collab:mouse_pointer", // multi pointer
};

View File

@ -24,7 +24,6 @@ import queryPaneSagas from "../src/sagas/QueryPaneSagas";
import saaSPaneSagas from "../src/sagas/SaaSPaneSagas";
import snipingModeSagas from "../src/sagas/SnipingModeSagas";
import themeSagas from "../src/sagas/ThemeSaga";
import websocketSagas from "../src/sagas/WebsocketSagas/WebsocketSagas";
import actionExecutionChangeListeners from "../src/sagas/WidgetLoadingSaga";
import widgetOperationSagas from "../src/sagas/WidgetOperationSagas";
import NavigationSagas from "../src/ee/sagas/NavigationSagas";
@ -51,7 +50,6 @@ export const sagasToRunForTests = [
formEvaluationChangeListener,
saaSPaneSagas,
globalSearchSagas,
websocketSagas,
debuggerSagas,
watchJSActionSagas,
selectionCanvasSagas,

View File

@ -12983,7 +12983,6 @@ __metadata:
showdown: ^1.9.1
simplebar-react: ^2.4.3
smartlook-client: ^8.0.0
socket.io-client: ^4.5.4
sql-formatter: 12.2.0
styled-components: ^5.3.6
tailwindcss: ^3.3.3
@ -17398,26 +17397,6 @@ __metadata:
languageName: node
linkType: hard
"engine.io-client@npm:~6.2.3":
version: 6.2.3
resolution: "engine.io-client@npm:6.2.3"
dependencies:
"@socket.io/component-emitter": ~3.1.0
debug: ~4.3.1
engine.io-parser: ~5.0.3
ws: ~8.2.3
xmlhttprequest-ssl: ~2.0.0
checksum: c09fb6429503a4a8a599ec1c4f67f100202e6e06588b67b81d386a4ebf8e81160cf7501ad6770ffe0a04575f41868f0a4cbf330b85de3f7cd24ebcf2bf9fc660
languageName: node
linkType: hard
"engine.io-parser@npm:~5.0.3":
version: 5.0.4
resolution: "engine.io-parser@npm:5.0.4"
checksum: d4ad0cef6ff63c350e35696da9bb3dbd180f67b56e93e90375010cc40393e6c0639b780d5680807e1d93a7e2e3d7b4a1c3b27cf75db28eb8cbf605bc1497da03
languageName: node
linkType: hard
"engine.io-parser@npm:~5.2.1":
version: 5.2.2
resolution: "engine.io-parser@npm:5.2.2"
@ -31137,19 +31116,7 @@ __metadata:
languageName: node
linkType: hard
"socket.io-client@npm:^4.5.4":
version: 4.5.4
resolution: "socket.io-client@npm:4.5.4"
dependencies:
"@socket.io/component-emitter": ~3.1.0
debug: ~4.3.2
engine.io-client: ~6.2.3
socket.io-parser: ~4.2.1
checksum: 8320ce4a96e9c28318b17037e412746b1d612cfba653c3c321c0e49042f0be9aeb8de67d5861e45e9aad32407bb4dd204bfe199565d78d5320aaf65253371b7f
languageName: node
linkType: hard
"socket.io-parser@npm:~4.2.1, socket.io-parser@npm:~4.2.4":
"socket.io-parser@npm:~4.2.4":
version: 4.2.4
resolution: "socket.io-parser@npm:4.2.4"
dependencies:
@ -34839,21 +34806,6 @@ __metadata:
languageName: node
linkType: hard
"ws@npm:~8.2.3":
version: 8.2.3
resolution: "ws@npm:8.2.3"
peerDependencies:
bufferutil: ^4.0.1
utf-8-validate: ^5.0.2
peerDependenciesMeta:
bufferutil:
optional: true
utf-8-validate:
optional: true
checksum: c869296ccb45f218ac6d32f8f614cd85b50a21fd434caf11646008eef92173be53490810c5c23aea31bc527902261fbfd7b062197eea341b26128d4be56a85e4
languageName: node
linkType: hard
"xlsx@https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz":
version: 0.19.3
resolution: "xlsx@https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz"
@ -34898,13 +34850,6 @@ __metadata:
languageName: node
linkType: hard
"xmlhttprequest-ssl@npm:~2.0.0":
version: 2.0.0
resolution: "xmlhttprequest-ssl@npm:2.0.0"
checksum: 1e98df67f004fec15754392a131343ea92e6ab5ac4d77e842378c5c4e4fd5b6a9134b169d96842cc19422d77b1606b8df84a5685562b3b698cb68441636f827e
languageName: node
linkType: hard
"xtend@npm:^4.0.0, xtend@npm:^4.0.1, xtend@npm:^4.0.2, xtend@npm:~4.0.1":
version: 4.0.2
resolution: "xtend@npm:4.0.2"