Skip to content

Commit 937fd9b

Browse files
committed
fix(replay): shutting down before example load
1 parent 0da7ea5 commit 937fd9b

File tree

13 files changed

+211
-123
lines changed

13 files changed

+211
-123
lines changed

examples/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
*.ts
22
*.js
33
!example.org.ts
4+
!proxy-example.js
45
!news.ycombinator.com.ts

replay/backend/Application.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,9 @@ export default class Application {
9090
if (key === '--replay-api-path') {
9191
ReplayApi.serverStartPath = value;
9292
}
93+
if (key === '--replay-node-path') {
94+
ReplayApi.nodePath = value;
95+
}
9396
}
9497

9598
if (this.shouldAppendToOpenReplayScript(replayMeta)) return;

replay/backend/api/ReplayTabState.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import ITickState from '~shared/interfaces/ITickState';
1414
import ReplayTime from '~backend/api/ReplayTime';
1515
import getResolvable from '~shared/utils/promise';
1616

17-
const loadWaitTime = 5e3;
1817
let pageCounter = 0;
1918

2019
export default class ReplayTabState extends EventEmitter {
@@ -34,6 +33,7 @@ export default class ReplayTabState extends EventEmitter {
3433
public currentPlaybarOffsetPct = 0;
3534
public replayTime: ReplayTime;
3635
public tabCreatedTime: string;
36+
public hasAllData = false;
3737

3838
public get isActive() {
3939
return this.listenerCount('tick:changes') > 0;
@@ -87,13 +87,7 @@ export default class ReplayTabState extends EventEmitter {
8787

8888
public transitionToNextTick() {
8989
const result = this.loadTick(this.currentTickIdx + 1);
90-
if (
91-
this.replayTime.close &&
92-
// give it a few seconds to get the rest of the data.
93-
// TODO: figure out how to confirm via http2 that all data is sent
94-
new Date().getTime() - this.replayTime.close.getTime() > loadWaitTime &&
95-
this.currentTickIdx === this.ticks.length - 1
96-
) {
90+
if (this.replayTime.close && this.hasAllData && this.currentTickIdx === this.ticks.length - 1) {
9791
this.currentPlaybarOffsetPct = 100;
9892
}
9993
return result;
@@ -188,7 +182,7 @@ export default class ReplayTabState extends EventEmitter {
188182
if (!newTick) return;
189183
if (!this.replayTime.close) {
190184
// give ticks time to load. TODO: need a better strategy for this
191-
if (new Date().getTime() - new Date(newTick.timestamp).getTime() < loadWaitTime) return;
185+
if (new Date().getTime() - new Date(newTick.timestamp).getTime() < 2e3) return;
192186
}
193187

194188
console.log('Loading tick %s', newTickIdx);
@@ -322,7 +316,7 @@ export default class ReplayTabState extends EventEmitter {
322316
tick.isNewDocumentTick = true;
323317
tick.documentOrigin = textContent;
324318
this.pages.push({
325-
id: pageCounter += 1,
319+
id: (pageCounter += 1),
326320
url: textContent,
327321
commandId,
328322
});

replay/backend/api/index.ts

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import ReplayTime from '~backend/api/ReplayTime';
1212
export default class ReplayApi {
1313
public static serverProcess: ChildProcess;
1414
public static serverStartPath: string;
15+
public static nodePath: string;
1516
private static sessions = new Set<http2.ClientHttp2Session>();
1617
private static localApiHost: string;
1718

@@ -21,6 +22,7 @@ export default class ReplayApi {
2122
public lastActivityDate: Date;
2223
public lastCommandName: string;
2324
public showUnresponsiveMessage = true;
25+
public hasAllData = false;
2426

2527
public onNewTab?: (tab: ReplayTabState) => any;
2628

@@ -52,25 +54,34 @@ export default class ReplayApi {
5254
ReplayApi.sessions.add(this.http2Session);
5355
this.http2Session.on('close', () => {
5456
ReplayApi.sessions.delete(this.http2Session);
57+
this.http2Session.unref();
5558
console.log('Http2 Session closed');
5659
});
5760
this.http2Session.on('stream', this.onStream.bind(this));
5861

5962
const request = this.http2Session
60-
.request({
61-
':path': `/`,
62-
'data-location': this.saSession.dataLocation,
63-
'session-name': this.saSession.name,
64-
'session-id': this.saSession.id,
65-
'script-instance-id': this.saSession.scriptInstanceId,
66-
'script-entrypoint': this.saSession.scriptEntrypoint,
67-
})
63+
.request(
64+
{
65+
':path': `/`,
66+
'data-location': this.saSession.dataLocation,
67+
'session-name': this.saSession.name,
68+
'session-id': this.saSession.id,
69+
'script-instance-id': this.saSession.scriptInstanceId,
70+
'script-entrypoint': this.saSession.scriptEntrypoint,
71+
},
72+
{ waitForTrailers: true },
73+
)
6874
.on('response', async headers => {
6975
const status = headers[':status'];
7076
if (status !== 200) {
7177
const data = await streamToJson<{ message: string }>(request);
7278
this.isReadyResolvable.reject(new Error(data.message ?? 'Unexpected Error'));
7379
}
80+
})
81+
.on('trailers', trailers => {
82+
console.log('Got Replay API Trailer', trailers);
83+
this.hasAllData = true;
84+
for (const tab of this.tabs) tab.hasAllData = true;
7485
});
7586
}
7687

@@ -194,8 +205,8 @@ export default class ReplayApi {
194205
!!ReplayApi.serverProcess,
195206
ReplayApi.sessions.size,
196207
);
197-
if (ReplayApi.serverProcess) ReplayApi.serverProcess.kill();
198208
for (const session of ReplayApi.sessions) session.destroy();
209+
if (ReplayApi.serverProcess) ReplayApi.serverProcess.kill();
199210
}
200211

201212
public static async connect(replay: IReplayMeta) {
@@ -217,8 +228,9 @@ export default class ReplayApi {
217228
const replayDir = __dirname.split(`${Path.sep}replay${Path.sep}`).shift();
218229
this.serverStartPath = Path.resolve(replayDir, 'session-state/api/start');
219230
}
231+
if (!this.nodePath) this.nodePath = 'node';
220232
console.log('Launching Replay API Server at %s', this.serverStartPath);
221-
const child = spawn(`node "${this.serverStartPath}"`, args, {
233+
const child = spawn(`${this.nodePath} "${this.serverStartPath}"`, args, {
222234
stdio: ['ignore', 'pipe', 'inherit'],
223235
shell: true,
224236
windowsHide: true,
@@ -229,6 +241,9 @@ export default class ReplayApi {
229241
},
230242
});
231243
this.serverProcess = child;
244+
this.serverProcess.once('exit', () => {
245+
this.serverProcess = null;
246+
});
232247

233248
child.stdout.setEncoding('utf8');
234249
const promise = await new Promise(resolve => {

replay/backend/models/ReplayView.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@ export default class ReplayView extends ViewBackend {
8989
}
9090

9191
public fixBounds(newBounds: { x: number; width: number; y: any; height: number }) {
92-
console.log('fixing bounds', newBounds, this.browserView.getBounds());
9392
this.playbarView.fixBounds({
9493
x: 0,
9594
y: newBounds.height + newBounds.y,
@@ -103,7 +102,6 @@ export default class ReplayView extends ViewBackend {
103102

104103
public attach() {
105104
if (this.isAttached) return;
106-
console.log('attaching replay');
107105
super.attach();
108106
this.playbarView.attach();
109107
this.interceptHttpRequests();

replay/backend/overlays/BaseOverlay.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export default class BaseOverlay {
9494
}
9595

9696
public hide() {
97-
if (!this.browserWindow) return;
97+
if (!this.browserWindow || this.browserWindow.isDestroyed()) return;
9898
if (!this.visible) return;
9999

100100
this.browserWindow.removeBrowserView(this.browserView);

replay/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export function replay(launchArgs: IReplayLaunchArgs) {
2323
`--replay-api-path="${apiPath}"`,
2424
`--replay-script-start-date="${scriptStartDate}"`,
2525
`--replay-api-server="${replayApiServer}"`,
26+
`--replay-node-path="${process.execPath}"`,
2627
];
2728

2829
if (isBinaryInstalled()) {

replay/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
"build": "yarn build:dist",
4747
"build:pack": "yarn build:icons && shx cp pack.sh ../build/replay/pack.sh && cd ../build/replay && electron-builder -mwl && ./pack.sh",
4848
"clean": "shx rm -rf ../build/replay/static && shx rm -rf ../build/replay/dist && tsc -b --clean tsconfig.json && tsc -b --clean frontend/tsconfig.json",
49-
"dev": "yarn build:backend && concurrently -k -n backend,frontend -c blue,green \"yarn start:backend\" \"cd frontend && yarn serve\"",
49+
"dev": "yarn build:backend && concurrently -k -n backend,frontend -c blue,green \"yarn start:backend\" \"cd frontend && yarn dev\"",
5050
"start:backend": "cross-env CLEAR_LOGS=true WEBPACK_DEV_SERVER_URL=http://localhost:8080 NODE_ENV=development electron ../build/replay",
5151
"start:frontend": "cd frontend && yarn dev",
5252
"start": "electron ../build/replay",

session-state/api/SessionLoader.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,14 +141,13 @@ export default class SessionLoader extends EventEmitter {
141141
public checkState() {
142142
if (!this.sessionState || this.session.closeDate) return;
143143
const scriptState = this.sessionState.checkForResponsive();
144-
const lastState = this.lastScriptState;
144+
const lastState = { ...(this.lastScriptState ?? {}) };
145145

146146
this.lastScriptState = scriptState;
147147
if (
148-
!lastState ||
149148
lastState.hasRecentErrors !== scriptState.hasRecentErrors ||
150149
lastState.closeDate !== scriptState.closeDate ||
151-
lastState.lastActivityDate !== scriptState.lastActivityDate ||
150+
lastState.lastActivityDate?.getTime() !== scriptState.lastActivityDate?.getTime() ||
152151
lastState.lastCommandName !== scriptState.lastCommandName
153152
) {
154153
this.emit('script-state', scriptState);

0 commit comments

Comments
 (0)