refactor(frontend/player):player lists
This commit is contained in:
parent
a111dc95e9
commit
f31ae3efa0
4 changed files with 158 additions and 63 deletions
|
|
@ -1,23 +1,76 @@
|
|||
import type { Message } from './messages'
|
||||
import ListWalker from './managers/ListWalker';
|
||||
import ListWalkerWithMarks from './managers/ListWalkerWithMarks';
|
||||
|
||||
export const LIST_NAMES = ["redux", "mobx", "vuex", "zustand", "ngrx", "graphql", "exceptions", "profiles"] as const;
|
||||
import type { Message } from './messages'
|
||||
|
||||
export const INITIAL_STATE = {}
|
||||
LIST_NAMES.forEach(name => {
|
||||
INITIAL_STATE[`${name}ListNow`] = []
|
||||
INITIAL_STATE[`${name}List`] = []
|
||||
})
|
||||
const SIMPLE_LIST_NAMES = [ "event", "redux", "mobx", "vuex", "zustand", "ngrx", "graphql", "exceptions", "profiles"] as const;
|
||||
const MARKED_LIST_NAMES = [ "log", "resource", "fetch", "stack" ] as const;
|
||||
//const entityNamesSimple = [ "event", "profile" ];
|
||||
|
||||
const LIST_NAMES = [...SIMPLE_LIST_NAMES, ...MARKED_LIST_NAMES ];
|
||||
|
||||
type ListsObject = {
|
||||
[key in typeof LIST_NAMES[number]]: ListWalker<any>
|
||||
}
|
||||
// TODO: provide correct types
|
||||
|
||||
export function initLists(): ListsObject {
|
||||
const lists: Partial<ListsObject> = {};
|
||||
for (var i = 0; i < LIST_NAMES.length; i++) {
|
||||
lists[LIST_NAMES[i]] = new ListWalker();
|
||||
export const INITIAL_STATE = LIST_NAMES.reduce((state, name) => {
|
||||
state[`${name}List`] = []
|
||||
state[`${name}ListNow`] = []
|
||||
if (MARKED_LIST_NAMES.includes(name)) {
|
||||
state[`${name}MarkedCountNow`] = 0
|
||||
state[`${name}MarkedCount`] = 0
|
||||
}
|
||||
return lists as ListsObject;
|
||||
return state
|
||||
}, {})
|
||||
|
||||
|
||||
type SimpleListsObject = {
|
||||
[key in typeof SIMPLE_LIST_NAMES[number]]: ListWalker<any>
|
||||
}
|
||||
type MarkedListsObject = {
|
||||
[key in typeof MARKED_LIST_NAMES[number]]: ListWalkerWithMarks<any>
|
||||
}
|
||||
type ListsObject = SimpleListsObject & MarkedListsObject
|
||||
|
||||
type InitialLists = {
|
||||
[key in typeof LIST_NAMES[number]]: any[]
|
||||
}
|
||||
|
||||
export default class Lists {
|
||||
lists: ListsObject
|
||||
constructor(initialLists: Partial<InitialLists> = {}) {
|
||||
const lists: Partial<ListsObject> = {}
|
||||
for (const name of SIMPLE_LIST_NAMES) {
|
||||
lists[name] = new ListWalker(initialLists[name])
|
||||
}
|
||||
for (const name of MARKED_LIST_NAMES) {
|
||||
// TODO: provide types
|
||||
lists[name] = new ListWalkerWithMarks((el) => el.isRed(), initialLists[name])
|
||||
}
|
||||
this.lists = lists as ListsObject
|
||||
}
|
||||
|
||||
getFullListsState() {
|
||||
return LIST_NAMES.reduce((state, name) => {
|
||||
state[`${name}List`] = this.lists[name].list
|
||||
return state
|
||||
}, MARKED_LIST_NAMES.reduce((state, name) => {
|
||||
state[`${name}MarkedCount`] = this.lists[name].markedCount
|
||||
return state
|
||||
}, {})
|
||||
)
|
||||
}
|
||||
|
||||
moveGetState(t: number)/* : Partial<State> */ {
|
||||
return LIST_NAMES.reduce((state, name) => {
|
||||
const lastMsg = this.lists[name].moveGetLast(t) // index: name === 'exceptions' ? undefined : index);
|
||||
if (lastMsg != null) {
|
||||
state[`${name}ListNow`] = this.lists[name].listNow
|
||||
}
|
||||
return state
|
||||
}, MARKED_LIST_NAMES.reduce((state, name) => {
|
||||
state[`${name}MarkedCountNow`] = this.lists[name].markedCountNow
|
||||
return state
|
||||
}, {})
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -9,12 +9,6 @@ import Log from 'Types/session/log';
|
|||
import { update } from '../store';
|
||||
import { toast } from 'react-toastify';
|
||||
|
||||
import {
|
||||
init as initListsDepr,
|
||||
append as listAppend,
|
||||
setStartTime as setListsStartTime
|
||||
} from '../lists';
|
||||
|
||||
import StatedScreen from './StatedScreen/StatedScreen';
|
||||
|
||||
import ListWalker from './managers/ListWalker';
|
||||
|
|
@ -32,7 +26,7 @@ import { decryptSessionBytes } from './network/crypto';
|
|||
|
||||
import { INITIAL_STATE as SUPER_INITIAL_STATE, State as SuperState } from './StatedScreen/StatedScreen';
|
||||
import { INITIAL_STATE as ASSIST_INITIAL_STATE, State as AssistState } from './managers/AssistManager';
|
||||
import { INITIAL_STATE as LISTS_INITIAL_STATE , LIST_NAMES, initLists } from './Lists';
|
||||
import Lists, { INITIAL_STATE as LISTS_INITIAL_STATE } from './Lists';
|
||||
|
||||
import type { PerformanceChartPoint } from './managers/PerformanceTrackManager';
|
||||
import type { SkipInterval } from './managers/ActivityManager';
|
||||
|
|
@ -100,7 +94,7 @@ export default class MessageDistributor extends StatedScreen {
|
|||
private scrollManager: ListWalker<SetViewportScroll> = new ListWalker();
|
||||
|
||||
private readonly decoder = new Decoder();
|
||||
private readonly lists = initLists();
|
||||
private readonly lists: Lists;
|
||||
|
||||
private activityManager: ActivityManager | null = null;
|
||||
|
||||
|
|
@ -118,28 +112,27 @@ export default class MessageDistributor extends StatedScreen {
|
|||
this.sessionStart = this.session.startedAt;
|
||||
|
||||
if (live) {
|
||||
initListsDepr({})
|
||||
this.lists = new Lists()
|
||||
this.assistManager.connect(this.session.agentToken);
|
||||
} else {
|
||||
this.activityManager = new ActivityManager(this.session.duration.milliseconds);
|
||||
/* == REFACTOR_ME == */
|
||||
const eventList = this.session.events.toJSON();
|
||||
|
||||
initListsDepr({
|
||||
event: eventList,
|
||||
stack: this.session.stackEvents.toJSON(),
|
||||
resource: this.session.resources.toJSON(),
|
||||
});
|
||||
|
||||
const eventList = session.events.toJSON();
|
||||
// TODO: fix types for events, remove immutable js
|
||||
eventList.forEach((e: Record<string, string>) => {
|
||||
if (e.type === EVENT_TYPES.LOCATION) { //TODO type system
|
||||
this.locationEventManager.append(e);
|
||||
}
|
||||
});
|
||||
this.session.errors.forEach((e: Record<string, string>) => {
|
||||
this.lists.exceptions.append(e);
|
||||
});
|
||||
})
|
||||
|
||||
this.lists = new Lists({
|
||||
event: eventList,
|
||||
stack: session.stackEvents.toJSON(),
|
||||
resource: session.resources.toJSON(),
|
||||
exceptions: session.errors.toJSON(),
|
||||
})
|
||||
|
||||
|
||||
/* === */
|
||||
this.loadMessages();
|
||||
}
|
||||
|
|
@ -187,13 +180,11 @@ export default class MessageDistributor extends StatedScreen {
|
|||
|
||||
private waitingForFiles: boolean = false
|
||||
private onFileReadSuccess = () => {
|
||||
const stateToUpdate: {[key:string]: any} = {
|
||||
const stateToUpdate = {
|
||||
performanceChartData: this.performanceTrackManager.chartData,
|
||||
performanceAvaliability: this.performanceTrackManager.avaliability,
|
||||
...this.lists.getFullListsState()
|
||||
}
|
||||
LIST_NAMES.forEach(key => {
|
||||
stateToUpdate[ `${ key }List` ] = this.lists[ key ].list
|
||||
})
|
||||
if (this.activityManager) {
|
||||
this.activityManager.end()
|
||||
stateToUpdate.skipIntervals = this.activityManager.list
|
||||
|
|
@ -304,7 +295,6 @@ export default class MessageDistributor extends StatedScreen {
|
|||
/* == REFACTOR_ME == */
|
||||
const lastLoadedLocationMsg = this.loadedLocationManager.moveGetLast(t, index);
|
||||
if (!!lastLoadedLocationMsg) {
|
||||
setListsStartTime(lastLoadedLocationMsg.time)
|
||||
this.navigationStartOffset = lastLoadedLocationMsg.navigationStart - this.sessionStart;
|
||||
}
|
||||
const llEvent = this.locationEventManager.moveGetLast(t, index);
|
||||
|
|
@ -340,14 +330,7 @@ export default class MessageDistributor extends StatedScreen {
|
|||
stateToUpdate.performanceChartTime = lastPerformanceTrackMessage.time;
|
||||
}
|
||||
|
||||
LIST_NAMES.forEach(key => {
|
||||
const lastMsg = this.lists[key].moveGetLast(t, key === 'exceptions' ? undefined : index);
|
||||
if (lastMsg != null) {
|
||||
// @ts-ignore TODO: fix types
|
||||
stateToUpdate[`${key}ListNow`] = this.lists[key].listNow;
|
||||
}
|
||||
});
|
||||
|
||||
Object.assign(stateToUpdate, this.lists.moveGetState(t))
|
||||
Object.keys(stateToUpdate).length > 0 && update(stateToUpdate);
|
||||
|
||||
/* Sequence of the managers is important here */
|
||||
|
|
@ -414,15 +397,15 @@ export default class MessageDistributor extends StatedScreen {
|
|||
/* Lists: */
|
||||
case "console_log":
|
||||
if (msg.level === 'debug') break;
|
||||
listAppend("log", Log({
|
||||
this.lists.lists.log.append(Log({
|
||||
level: msg.level,
|
||||
value: msg.value,
|
||||
time,
|
||||
index,
|
||||
}));
|
||||
}))
|
||||
break;
|
||||
case "fetch":
|
||||
listAppend("fetch", Resource({
|
||||
this.lists.lists.fetch.append(Resource({
|
||||
method: msg.method,
|
||||
url: msg.url,
|
||||
payload: msg.request,
|
||||
|
|
@ -469,42 +452,42 @@ export default class MessageDistributor extends StatedScreen {
|
|||
decoded = this.decodeStateMessage(msg, ["state", "action"]);
|
||||
logger.log('redux', decoded)
|
||||
if (decoded != null) {
|
||||
this.lists.redux.append(decoded);
|
||||
this.lists.lists.redux.append(decoded);
|
||||
}
|
||||
break;
|
||||
case "ng_rx":
|
||||
decoded = this.decodeStateMessage(msg, ["state", "action"]);
|
||||
logger.log('ngrx', decoded)
|
||||
if (decoded != null) {
|
||||
this.lists.ngrx.append(decoded);
|
||||
this.lists.lists.ngrx.append(decoded);
|
||||
}
|
||||
break;
|
||||
case "vuex":
|
||||
decoded = this.decodeStateMessage(msg, ["state", "mutation"]);
|
||||
logger.log('vuex', decoded)
|
||||
if (decoded != null) {
|
||||
this.lists.vuex.append(decoded);
|
||||
this.lists.lists.vuex.append(decoded);
|
||||
}
|
||||
break;
|
||||
case "zustand":
|
||||
decoded = this.decodeStateMessage(msg, ["state", "mutation"])
|
||||
logger.log('zustand', decoded)
|
||||
if (decoded != null) {
|
||||
this.lists.zustand.append(decoded)
|
||||
this.lists.lists.zustand.append(decoded)
|
||||
}
|
||||
case "mob_x":
|
||||
decoded = this.decodeStateMessage(msg, ["payload"]);
|
||||
logger.log('mobx', decoded)
|
||||
|
||||
if (decoded != null) {
|
||||
this.lists.mobx.append(decoded);
|
||||
this.lists.lists.mobx.append(decoded);
|
||||
}
|
||||
break;
|
||||
case "graph_ql":
|
||||
this.lists.graphql.append(msg);
|
||||
this.lists.lists.graphql.append(msg);
|
||||
break;
|
||||
case "profiler":
|
||||
this.lists.profiles.append(msg);
|
||||
this.lists.lists.profiles.append(msg);
|
||||
break;
|
||||
default:
|
||||
switch (msg.tp) {
|
||||
|
|
|
|||
|
|
@ -79,6 +79,23 @@ export default class ListWalker<T extends Timed> {
|
|||
return this.p;
|
||||
}
|
||||
|
||||
private hasNext() {
|
||||
return this.p < this.length
|
||||
}
|
||||
private hasPrev() {
|
||||
return this.p > 0
|
||||
}
|
||||
protected moveNext(): T | null {
|
||||
return this.hasNext()
|
||||
? this.list[ this.p++ ]
|
||||
: null
|
||||
}
|
||||
protected movePrev(): T | null {
|
||||
return this.hasPrev()
|
||||
? this.list[ --this.p ]
|
||||
: null
|
||||
}
|
||||
|
||||
/*
|
||||
Returns last message with the time <= t.
|
||||
Assumed that the current message is already handled so
|
||||
|
|
@ -94,11 +111,11 @@ export default class ListWalker<T extends Timed> {
|
|||
|
||||
let changed = false;
|
||||
while (this.p < this.length && this.list[this.p][key] <= val) {
|
||||
this.p++;
|
||||
this.moveNext()
|
||||
changed = true;
|
||||
}
|
||||
while (this.p > 0 && this.list[ this.p - 1 ][key] > val) {
|
||||
this.p--;
|
||||
this.movePrev()
|
||||
changed = true;
|
||||
}
|
||||
return changed ? this.list[ this.p - 1 ] : null;
|
||||
|
|
@ -112,10 +129,10 @@ export default class ListWalker<T extends Timed> {
|
|||
|
||||
const list = this.list
|
||||
while (list[this.p] && list[this.p].time <= t) {
|
||||
fn(list[ this.p++ ]);
|
||||
fn(this.moveNext())
|
||||
}
|
||||
while (fnBack && this.p > 0 && list[ this.p - 1 ].time > t) {
|
||||
fnBack(list[ --this.p ]);
|
||||
fnBack(this.movePrev());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
import type { Timed } from '../messages/timed';
|
||||
import ListWalker from './ListWalker'
|
||||
|
||||
|
||||
type CheckFn<T> = (t: T) => boolean
|
||||
|
||||
|
||||
export default class ListWalkerWithMarks<T extends Timed> extends ListWalker<T> {
|
||||
private _markCountNow: number = 0
|
||||
private _markCount: number = 0
|
||||
constructor(private isMarked: CheckFn<T>, initialList: T[] = []) {
|
||||
super(initialList)
|
||||
this._markCount = initialList.reduce((n, item) => isMarked(item) ? n+1 : n, 0)
|
||||
}
|
||||
|
||||
append(item: T) {
|
||||
if (this.isMarked(item)) { this._markCount++ }
|
||||
super.append(item)
|
||||
}
|
||||
|
||||
protected moveNext() {
|
||||
const val = super.moveNext()
|
||||
if (val && this.isMarked(val)) {
|
||||
this._markCountNow++
|
||||
}
|
||||
return val
|
||||
}
|
||||
protected movePrev() {
|
||||
const val = super.movePrev()
|
||||
if (val && this.isMarked(val)) {
|
||||
this._markCountNow--
|
||||
}
|
||||
return val
|
||||
}
|
||||
get markedCountNow(): number {
|
||||
return this._markCountNow
|
||||
}
|
||||
get markedCount(): number {
|
||||
return this._markCount
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue