Skip to content

Commit 4297f1d

Browse files
christianalfoniCompuIves
authored andcommitted
Perf performance on file sync (codesandbox#2591)
* Perf performance on file sync * improve readability * add savedCode to tracking of structure changes * improve rendering of Files * fix wrong refactor * PureComponent on moduleEntry * explicit creation of error and correction
1 parent db2dd20 commit 4297f1d

File tree

15 files changed

+266
-214
lines changed

15 files changed

+266
-214
lines changed

packages/app/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,9 @@
150150
"normalizr": "^3.2.3",
151151
"onigasm": "^2.2.1",
152152
"ot": "^0.0.15",
153-
"overmind": "^19.1.1",
153+
"overmind": "^19.3.0-1569928101550",
154154
"overmind-devtools": "^19.0.0",
155-
"overmind-react": "^20.1.1",
155+
"overmind-react": "^20.3.0-1569928101550",
156156
"phoenix": "^1.3.0",
157157
"postcss": "^6.0.9",
158158
"postcss-selector-parser": "^2.2.3",

packages/app/src/app/overmind/effects/api/index.ts

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,27 @@
1+
import { TemplateType } from '@codesandbox/common/lib/templates';
12
import {
23
CurrentUser,
4+
CustomTemplate,
35
Dependency,
4-
Sandbox,
5-
Module,
6-
GitChanges,
7-
EnvironmentVariable,
8-
PopularSandboxes,
9-
SandboxPick,
10-
PickedSandboxes,
11-
UploadedFilesInfo,
126
Directory,
13-
GitInfo,
7+
EnvironmentVariable,
8+
GitChanges,
149
GitCommit,
10+
GitInfo,
1511
GitPr,
12+
Module,
1613
PaymentDetails,
14+
PickedSandboxes,
15+
PopularSandboxes,
1716
Profile,
17+
Sandbox,
18+
SandboxPick,
19+
UploadedFilesInfo,
1820
UserSandbox,
19-
CustomTemplate,
2021
} from '@codesandbox/common/lib/types';
21-
import { TemplateType } from '@codesandbox/common/lib/templates';
2222
import { client } from 'app/graphql/client';
2323
import { LIST_TEMPLATES } from 'app/pages/Dashboard/queries';
24+
2425
import apiFactory, { Api, ApiConfig } from './apiFactory';
2526

2627
let api: Api;
@@ -70,15 +71,28 @@ export default {
7071
...module,
7172
savedCode: null,
7273
isNotSynced: false,
74+
errors: [],
75+
corrections: [],
7376
})),
7477
};
7578
},
76-
forkSandbox(id: string, body?: unknown): Promise<Sandbox> {
79+
async forkSandbox(id: string, body?: unknown): Promise<Sandbox> {
7780
const url = id.includes('/')
7881
? `/sandboxes/fork/${id}`
7982
: `/sandboxes/${id}/fork`;
8083

81-
return api.post(url, body || {});
84+
const sandbox = await api.post<Sandbox>(url, body || {});
85+
86+
return {
87+
...sandbox,
88+
modules: sandbox.modules.map(module => ({
89+
...module,
90+
savedCode: null,
91+
isNotSynced: false,
92+
errors: [],
93+
corrections: [],
94+
})),
95+
};
8296
},
8397
createModule(sandboxId: string, module: Module): Promise<Module> {
8498
return api.post(`/sandboxes/${sandboxId}/modules`, {

packages/app/src/app/overmind/effects/fsSync.ts

Lines changed: 47 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
import { getAbsoluteDependencies } from '@codesandbox/common/lib/utils/dependencies';
2-
import { protocolAndHost } from '@codesandbox/common/lib/utils/url-generator';
3-
42
import { getGlobal } from '@codesandbox/common/lib/utils/global';
5-
import { Module } from '@codesandbox/common/lib/types';
3+
import { protocolAndHost } from '@codesandbox/common/lib/utils/url-generator';
4+
import { json } from 'overmind';
65

76
const global = getGlobal() as Window & { BrowserFS: any };
87

98
const fs = global.BrowserFS.BFSRequire('fs');
109
const SERVICE_URL = 'https://ata-fetcher.cloud/api/v5/typings';
1110

12-
let fileInterval;
1311
let lastMTime = new Date(0);
1412

1513
function sendTypes() {
@@ -101,81 +99,61 @@ async function syncDependencyTypings(
10199
}
102100
}
103101

104-
let getCurrentSandboxId;
105-
let getModulesByPath;
106-
107-
export default {
108-
initialize(options: {
109-
getCurrentSandboxId: () => string;
110-
getModulesByPath: () => {
111-
[path: string]: Module;
112-
};
113-
}) {
114-
getCurrentSandboxId = options.getCurrentSandboxId; // eslint-disable-line prefer-destructuring
115-
getModulesByPath = options.getModulesByPath; // eslint-disable-line prefer-destructuring
116-
},
117-
syncCurrentSandbox() {
118-
if (fileInterval) {
119-
clearInterval(fileInterval);
120-
}
102+
function sendFiles(modulesByPath) {
103+
global.postMessage(
104+
{
105+
$broadcast: true,
106+
$type: 'file-sync',
107+
$data: json(modulesByPath),
108+
},
109+
protocolAndHost()
110+
);
121111

122-
const sendFiles = () => {
123-
if (getCurrentSandboxId()) {
124-
const modulesByPath = getModulesByPath();
125-
126-
global.postMessage(
127-
{
128-
$broadcast: true,
129-
$type: 'file-sync',
130-
$data: modulesByPath,
131-
},
132-
protocolAndHost()
133-
);
112+
try {
113+
fs.stat('/sandbox/package.json', (packageJsonError, stat) => {
114+
if (packageJsonError) {
115+
return;
134116
}
135-
};
136-
137-
fileInterval = setInterval(() => {
138-
sendFiles();
139117

140-
try {
141-
fs.stat('/sandbox/package.json', (packageJsonError, stat) => {
142-
if (packageJsonError) {
143-
return;
118+
if (stat.mtime.toString() !== lastMTime.toString()) {
119+
lastMTime = stat.mtime;
120+
121+
fs.readFile(
122+
'/sandbox/package.json',
123+
async (packageJsonReadError, rv) => {
124+
if (packageJsonReadError) {
125+
console.error(packageJsonReadError);
126+
return;
127+
}
128+
129+
fs.stat('/sandbox/tsconfig.json', (tsConfigError, result) => {
130+
// If tsconfig exists we want to sync the types
131+
syncDependencyTypings(
132+
rv.toString(),
133+
Boolean(tsConfigError) || !result
134+
);
135+
});
144136
}
145-
146-
if (stat.mtime.toString() !== lastMTime.toString()) {
147-
lastMTime = stat.mtime;
148-
149-
fs.readFile(
150-
'/sandbox/package.json',
151-
async (packageJsonReadError, rv) => {
152-
if (packageJsonReadError) {
153-
console.error(packageJsonReadError);
154-
return;
155-
}
156-
157-
fs.stat('/sandbox/tsconfig.json', (tsConfigError, result) => {
158-
// If tsconfig exists we want to sync the types
159-
syncDependencyTypings(
160-
rv.toString(),
161-
Boolean(tsConfigError) || !result
162-
);
163-
});
164-
}
165-
);
166-
}
167-
});
168-
} catch (e) {
169-
// Do nothing
137+
);
170138
}
171-
}, 1000);
139+
});
140+
} catch (e) {
141+
// Do nothing
142+
}
143+
}
172144

173-
// eslint-disable-next-line
145+
export default {
146+
initialize(options: {
147+
onModulesByPathChange: (modulesByPath: any) => void;
148+
getModulesByPath: () => any;
149+
}) {
174150
self.addEventListener('message', evt => {
175151
if (evt.data.$type === 'request-data') {
176152
sendTypes();
177-
sendFiles();
153+
sendFiles(options.getModulesByPath());
178154
}
179155
});
156+
157+
options.onModulesByPathChange(sendFiles);
180158
},
181159
};

packages/app/src/app/overmind/internalActions.ts

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
import { identify, setUserId } from '@codesandbox/common/lib/utils/analytics';
1+
import { generateFileFromSandbox as generatePackageJsonFromSandbox } from '@codesandbox/common/lib/templates/configuration/package-json';
22
import {
3-
Sandbox,
4-
NotificationButton,
5-
TabType,
63
ModuleTab,
7-
ServerStatus,
4+
NotificationButton,
5+
Sandbox,
86
ServerContainerStatus,
7+
ServerStatus,
8+
TabType,
99
} from '@codesandbox/common/lib/types';
10-
import { generateFileFromSandbox as generatePackageJsonFromSandbox } from '@codesandbox/common/lib/templates/configuration/package-json';
11-
import { Action, AsyncAction } from '.';
12-
import { parseConfigurations } from './utils/parse-configurations';
13-
import { defaultOpenedModule, mainModule } from './utils/main-module';
14-
import getItems from './utils/items';
10+
import { identify, setUserId } from '@codesandbox/common/lib/utils/analytics';
11+
1512
import { createOptimisticModule } from './utils/common';
13+
import getItems from './utils/items';
14+
import { defaultOpenedModule, mainModule } from './utils/main-module';
15+
import { parseConfigurations } from './utils/parse-configurations';
16+
import { Action, AsyncAction } from '.';
1617

1718
export const signIn: AsyncAction<{ useExtraScopes: boolean }> = async (
1819
{ state, effects, actions },
@@ -257,8 +258,6 @@ export const setCurrentSandbox: AsyncAction<Sandbox> = async (
257258

258259
effects.executor.setupExecutor();
259260

260-
effects.fsSync.syncCurrentSandbox();
261-
262261
/*
263262
There seems to be a race condition here? Verify if this still happens with Overmind
264263
*/

packages/app/src/app/overmind/namespaces/editor/actions.ts

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
1-
import { Action, AsyncAction } from 'app/overmind';
2-
import { sortObjectByKeys } from 'app/overmind/utils/common';
3-
import { withLoadApp, withOwnedSandbox } from 'app/overmind/factories';
4-
import { json } from 'overmind';
5-
import { clearCorrectionsFromAction } from 'app/utils/corrections';
1+
import { resolveModule } from '@codesandbox/common/lib/sandbox/modules';
62
import {
7-
WindowOrientation,
83
EnvironmentVariable,
4+
ModuleCorrection,
5+
ModuleError,
96
ModuleTab,
7+
WindowOrientation,
108
} from '@codesandbox/common/lib/types';
9+
import { Action, AsyncAction } from 'app/overmind';
10+
import { withLoadApp, withOwnedSandbox } from 'app/overmind/factories';
11+
import { sortObjectByKeys } from 'app/overmind/utils/common';
1112
import {
1213
addDevToolsTab as addDevToolsTabUtil,
13-
moveDevToolsTab as moveDevToolsTabUtil,
1414
closeDevToolsTab as closeDevToolsTabUtil,
15+
moveDevToolsTab as moveDevToolsTabUtil,
1516
} from 'app/pages/Sandbox/Editor/Content/utils';
17+
import { clearCorrectionsFromAction } from 'app/utils/corrections';
18+
import { json } from 'overmind';
19+
1620
import * as internalActions from './internalActions';
1721

1822
export const internal = internalActions;
@@ -369,6 +373,15 @@ export const prettifyClicked: AsyncAction = async ({
369373

370374
export const errorsCleared: Action = ({ state }) => {
371375
if (state.editor.errors.length) {
376+
state.editor.errors.forEach(error => {
377+
const module = resolveModule(
378+
error.path,
379+
state.editor.currentSandbox.modules,
380+
state.editor.currentSandbox.directories
381+
);
382+
383+
module.errors = [];
384+
});
372385
state.editor.errors = [];
373386
}
374387
};
@@ -490,8 +503,7 @@ export const previewActionReceived: Action<{
490503
});
491504
break;
492505
case 'show-error': {
493-
const error = {
494-
moduleId: action.module ? action.module.id : undefined,
506+
const error: ModuleError = {
495507
column: action.column,
496508
line: action.line,
497509
columnEnd: action.columnEnd,
@@ -500,13 +512,21 @@ export const previewActionReceived: Action<{
500512
title: action.title,
501513
path: action.path,
502514
source: action.source,
515+
severity: action.severity,
516+
type: action.type,
503517
};
518+
const module = resolveModule(
519+
error.path,
520+
state.editor.currentSandbox.modules,
521+
state.editor.currentSandbox.directories
522+
);
504523

524+
module.errors.push(json(error));
505525
state.editor.errors.push(error);
506526
break;
507527
}
508528
case 'show-correction': {
509-
const correction = {
529+
const correction: ModuleCorrection = {
510530
path: action.path,
511531
column: action.column,
512532
line: action.line,
@@ -516,8 +536,14 @@ export const previewActionReceived: Action<{
516536
source: action.source,
517537
severity: action.severity,
518538
};
539+
const module = resolveModule(
540+
correction.path,
541+
state.editor.currentSandbox.modules,
542+
state.editor.currentSandbox.directories
543+
);
519544

520545
state.editor.corrections.push(correction);
546+
module.corrections.push(json(correction));
521547
break;
522548
}
523549
case 'clear-errors': {
@@ -526,6 +552,15 @@ export const previewActionReceived: Action<{
526552
const newErrors = clearCorrectionsFromAction(currentErrors, action);
527553

528554
if (newErrors.length !== currentErrors.length) {
555+
state.editor.errors.forEach(error => {
556+
const module = resolveModule(
557+
error.path,
558+
state.editor.currentSandbox.modules,
559+
state.editor.currentSandbox.directories
560+
);
561+
562+
module.errors = [];
563+
});
529564
state.editor.errors = newErrors;
530565
}
531566
break;
@@ -539,6 +574,15 @@ export const previewActionReceived: Action<{
539574
);
540575

541576
if (newCorrections.length !== currentCorrections.length) {
577+
state.editor.corrections.forEach(correction => {
578+
const module = resolveModule(
579+
correction.path,
580+
state.editor.currentSandbox.modules,
581+
state.editor.currentSandbox.directories
582+
);
583+
584+
module.corrections = [];
585+
});
542586
state.editor.corrections = newCorrections;
543587
}
544588
break;

0 commit comments

Comments
 (0)