Skip to content

Commit

Permalink
Merge pull request #990 from eclipsesource/976-JSON-RPC
Browse files Browse the repository at this point in the history
Refactor server communication to JSON-RPC
  • Loading branch information
bhufmann authored Sep 15, 2023
2 parents abe6fad + b5b68e1 commit a1d5a0c
Show file tree
Hide file tree
Showing 26 changed files with 708 additions and 144 deletions.
6 changes: 3 additions & 3 deletions doc/adr/0002/graphql-server-prototype/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// [1] https://www.apollographql.com/docs/apollo-server/getting-started/#step-3-define-your-graphql-schema

const { ApolloServer, gql } = require('apollo-server');
const { TspClient } = require('tsp-typescript-client/lib/protocol/tsp-client');
const { HttpTspClient } = require('tsp-typescript-client/lib/protocol/http-tsp-client');

// A schema is a collection of type definitions (hence "typeDefs").
const typeDefs = gql`
Expand All @@ -21,7 +21,7 @@ const baseUrl = "http://localhost:8080/tsp/api";
const resolvers = {
Query: {
async status() {
const tspClient = new TspClient(baseUrl);
const tspClient = new HttpTspClient(baseUrl);
try {
const response = await tspClient.checkHealth();
if (response.isOk()) {
Expand All @@ -37,7 +37,7 @@ const resolvers = {
},
async traces() {
// Same simple approach as above. Returns how many traces only.
const tspClient = new TspClient(baseUrl);
const tspClient = new HttpTspClient(baseUrl);
try {
const response = await tspClient.fetchTraces();
if (response.isOk()) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"private": true,
"scripts": {
"prepare": "yarn -s tsref && yarn -s tsbuild && yarn -s download:plugins && yarn -s prepare:examples",
"prepare": "yarn -s clean && yarn -s tsref && yarn -s tsbuild && yarn -s download:plugins && yarn -s prepare:examples",
"tsref": "node scripts/typescript-references.js",
"tsbuild": "tsc -b",
"tswatch": "tsc -b -w",
Expand Down
11 changes: 7 additions & 4 deletions packages/base/src/experiment-manager.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Trace } from 'tsp-typescript-client/lib/models/trace';
import { TspClient } from 'tsp-typescript-client/lib/protocol/tsp-client';
import { ITspClient } from 'tsp-typescript-client/lib/protocol/tsp-client';
import { Query } from 'tsp-typescript-client/lib/models/query/query';
import { OutputDescriptor } from 'tsp-typescript-client/lib/models/output-descriptor';
import { Experiment } from 'tsp-typescript-client/lib/models/experiment';
Expand All @@ -9,10 +9,10 @@ import { signalManager, Signals } from './signals/signal-manager';

export class ExperimentManager {
private fOpenExperiments: Map<string, Experiment> = new Map();
private fTspClient: TspClient;
private fTspClient: ITspClient;
private fTraceManager: TraceManager;

constructor(tspClient: TspClient, traceManager: TraceManager) {
constructor(tspClient: ITspClient, traceManager: TraceManager) {
this.fTspClient = tspClient;
this.fTraceManager = traceManager;
signalManager().on(Signals.EXPERIMENT_DELETED, (experiment: Experiment) =>
Expand Down Expand Up @@ -79,7 +79,10 @@ export class ExperimentManager {
traceURIs.push(traces[i].UUID);
}

const tryCreate = async function (tspClient: TspClient, retry: number): Promise<TspClientResponse<Experiment>> {
const tryCreate = async function (
tspClient: ITspClient,
retry: number
): Promise<TspClientResponse<Experiment>> {
return tspClient.createExperiment(
new Query({
name: retry === 0 ? name : name + '(' + retry + ')',
Expand Down
30 changes: 21 additions & 9 deletions packages/base/src/lazy-tsp-client.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,47 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

import { TspClient } from 'tsp-typescript-client';
import { ITspClient } from 'tsp-typescript-client';
import { HttpTspClient } from 'tsp-typescript-client/lib/protocol/http-tsp-client';

/**
* Hack!
* The `LazyTspClient` replaces _every_ method with an asynchronous one.
* Only keep methods, discard properties.
*/
export type LazyTspClient = {
[K in keyof TspClient]: TspClient[K] extends (...args: infer A) => infer R | Promise<infer R>
[K in keyof ITspClient]: ITspClient[K] extends (...args: infer A) => infer R | Promise<infer R>
? (...args: A) => Promise<R>
: never; // Discard property.
};

export type LazyTspClientFactory = typeof LazyTspClientFactory;
export function LazyTspClientFactory(url: Promise<string>): TspClient {
// All methods from the `TspClient` are asynchronous. The `LazyTspClient`
export function LazyTspClientFactory(provider: () => Promise<string>): ITspClient {
// All methods from the `HttpTspClient` are asynchronous. The `LazyTspClient`
// will just delay each call to its methods by first awaiting for the
// asynchronous `baseUrl` resolution to then get a valid `TspClient`.
const tspClientPromise = url.then(baseUrl => new TspClient(baseUrl));
// asynchronous `baseUrl` resolution to then get a valid `HttpTspClient`.

// Save the current HttpTspClient and the URL used for it.
let tspClient: HttpTspClient;
let lastUrl: string;
// eslint-disable-next-line no-null/no-null
return new Proxy(Object.create(null), {
get(target, property, _receiver) {
let method = target[property];
if (!method) {
target[property] = method = async (...args: any[]) => {
const tspClient = (await tspClientPromise) as any;
return tspClient[property](...args);
tspClient = await provider().then(baseUrl => {
// If the url has not been updated keep the same client.
if (lastUrl === baseUrl) {
return tspClient;
}
// If the url has changed save it and create a new client.
lastUrl = baseUrl;
return new HttpTspClient(baseUrl);
});
return (tspClient as any)[property](...args);
};
}
return method;
}
}) as LazyTspClient as TspClient;
}) as LazyTspClient as ITspClient;
}
10 changes: 5 additions & 5 deletions packages/base/src/trace-manager.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { Trace } from 'tsp-typescript-client/lib/models/trace';
import { TspClient } from 'tsp-typescript-client/lib/protocol/tsp-client';
import { ITspClient } from 'tsp-typescript-client/lib/protocol/tsp-client';
import { Query } from 'tsp-typescript-client/lib/models/query/query';
import { OutputDescriptor } from 'tsp-typescript-client/lib/models/output-descriptor';
import { TspClientResponse } from 'tsp-typescript-client/lib/protocol/tsp-client-response';
import { signalManager } from './signals/signal-manager';

export class TraceManager {
private fOpenTraces: Map<string, Trace> = new Map();
private fTspClient: TspClient;
private fTspClient: ITspClient;

constructor(tspClient: TspClient) {
constructor(tspClient: ITspClient) {
this.fTspClient = tspClient;
}

Expand Down Expand Up @@ -69,7 +69,7 @@ export class TraceManager {
async openTrace(traceURI: string, traceName?: string): Promise<Trace | undefined> {
const name = traceName ? traceName : traceURI.replace(/\/$/, '').replace(/(.*\/)?/, '');

const tryOpen = async function (tspClient: TspClient, retry: number): Promise<TspClientResponse<Trace>> {
const tryOpen = async function (tspClient: ITspClient, retry: number): Promise<TspClientResponse<Trace>> {
return tspClient.openTrace(
new Query({
name: retry === 0 ? name : name + '(' + retry + ')',
Expand Down Expand Up @@ -103,7 +103,7 @@ export class TraceManager {
if (currentTrace) {
const traceResponse = await this.fTspClient.fetchTrace(currentTrace.UUID);
const trace = traceResponse.getModel();
if (trace && traceResponse.isOk) {
if (trace && traceResponse.isOk()) {
this.fOpenTraces.set(traceUUID, trace);
return trace;
}
Expand Down
6 changes: 3 additions & 3 deletions packages/base/src/tsp-client-provider.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { TspClient } from 'tsp-typescript-client/lib/protocol/tsp-client';
import { ITspClient } from 'tsp-typescript-client/lib/protocol/tsp-client';
import { ExperimentManager } from './experiment-manager';
import { TraceManager } from './trace-manager';

export interface ITspClientProvider {
getTspClient(): TspClient;
getTspClient(): ITspClient;
getTraceManager(): TraceManager;
getExperimentManager(): ExperimentManager;
/**
* Add a listener for trace server url changes
* @param listener The listener function to be called when the url is
* changed
*/
addTspClientChangeListener(listener: (tspClient: TspClient) => void): void;
addTspClientChangeListener(listener: (tspClient: ITspClient) => void): void;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { CellRenderer, LoadingRenderer, SearchFilterRenderer } from '../table-re
import { AbstractOutputProps } from '../abstract-output-component';
import { TimeGraphUnitController } from 'timeline-chart/lib/time-graph-unit-controller';
import { TimeRange } from 'traceviewer-base/lib/utils/time-range';
import { TspClient } from 'tsp-typescript-client/lib/protocol/tsp-client';
import { HttpTspClient } from 'tsp-typescript-client/lib/protocol/http-tsp-client';
import { ColDef, Column, ColumnApi, GridApi, IRowModel, RowNode } from 'ag-grid-community';

describe('<TableOutputComponent />', () => {
Expand Down Expand Up @@ -38,7 +38,7 @@ describe('<TableOutputComponent />', () => {
componentLeft: 0,
chartOffset: 0
},
tspClient: new TspClient('testURL'),
tspClient: new HttpTspClient('testURL'),
traceId: '0',
outputDescriptor: {
id: '0',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react';
import { OutputDescriptor } from 'tsp-typescript-client/lib/models/output-descriptor';
import { TspClient } from 'tsp-typescript-client/lib/protocol/tsp-client';
import { ITspClient } from 'tsp-typescript-client/lib/protocol/tsp-client';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faBars, faSpinner, faThumbtack, faTimes } from '@fortawesome/free-solid-svg-icons';
import { TimeGraphUnitController } from 'timeline-chart/lib/time-graph-unit-controller';
Expand All @@ -11,16 +11,10 @@ import { TooltipComponent } from './tooltip-component';
import { TooltipXYComponent } from './tooltip-xy-component';
import { ResponseStatus } from 'tsp-typescript-client/lib/models/response/responses';
import { signalManager } from 'traceviewer-base/lib/signals/signal-manager';
import {
DropDownComponent,
DropDownSubSection,
OptionCheckBoxState,
OptionState,
OptionType
} from './drop-down-component';
import { DropDownComponent, DropDownSubSection, OptionState } from './drop-down-component';

export interface AbstractOutputProps {
tspClient: TspClient;
tspClient: ITspClient;
tooltipComponent: TooltipComponent | null;
tooltipXYComponent: TooltipXYComponent | null;
traceId: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { TspClient } from 'tsp-typescript-client/lib/protocol/tsp-client';
import { ITspClient } from 'tsp-typescript-client/lib/protocol/tsp-client';
import { QueryHelper } from 'tsp-typescript-client/lib/models/query/query-helper';
import { OutputStyleModel, OutputElementStyle } from 'tsp-typescript-client/lib/models/styles';
import { StyleProperties } from './style-properties';

export class StyleProvider {
private tspClient: TspClient;
private tspClient: ITspClient;
private traceId: string;
private outputId: string;

private tmpStyleObject: { [key: string]: { [key: string]: { [key: string]: any } } };

private styleModel: OutputStyleModel | undefined;

constructor(outputId: string, traceId: string, tspClient: TspClient) {
constructor(outputId: string, traceId: string, tspClient: ITspClient) {
this.outputId = outputId;
this.tspClient = tspClient;
this.traceId = traceId;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { TspClient } from 'tsp-typescript-client/lib/protocol/tsp-client';
import { ITspClient } from 'tsp-typescript-client/lib/protocol/tsp-client';
import {
TimeGraphArrow,
TimeGraphEntry,
Expand All @@ -21,15 +21,15 @@ enum ElementType {
}

export class TspDataProvider {
private client: TspClient;
private client: ITspClient;
private outputId: string;
private traceUUID: string;
private timeGraphEntries: TimeGraphEntry[];
private timeGraphRows: TimeGraphRow[];

public totalRange: bigint;

constructor(client: TspClient, traceUUID: string, outputId: string) {
constructor(client: ITspClient, traceUUID: string, outputId: string) {
this.timeGraphEntries = [];
this.timeGraphRows = [];
this.client = client;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { TimelineChart } from 'timeline-chart/lib/time-graph-model';
import { TimeGraphUnitController } from 'timeline-chart/lib/time-graph-unit-controller';
import { OutputDescriptor } from 'tsp-typescript-client/lib/models/output-descriptor';
import { Experiment } from 'tsp-typescript-client/lib/models/experiment';
import { TspClient } from 'tsp-typescript-client/lib/protocol/tsp-client';
import { ITspClient } from 'tsp-typescript-client/lib/protocol/tsp-client';
import { TimeRange, TimeRangeString } from 'traceviewer-base/lib/utils/time-range';
import { TableOutputComponent } from './table-output-component';
import { TimegraphOutputComponent } from './timegraph-output-component';
Expand All @@ -34,7 +34,7 @@ import { TimeRangeUpdatePayload } from 'traceviewer-base/lib/signals/time-range-
const ResponsiveGridLayout = WidthProvider(Responsive);

export interface TraceContextProps {
tspClient: TspClient;
tspClient: ITspClient;
experiment: Experiment;
outputs: OutputDescriptor[];
overviewDescriptor?: OutputDescriptor; // The default output descriptor for the overview
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import React from 'react';
import { OutputDescriptor, TspClient } from 'tsp-typescript-client';
import { OutputDescriptor, ITspClient } from 'tsp-typescript-client';
import { AbstractDialogComponent, DialogComponentProps } from './abstract-dialog-component';
import { signalManager } from 'traceviewer-base/lib/signals/signal-manager';
import { AvailableViewsComponent } from './utils/available-views-component';

export interface TraceOverviewSelectionComponentProps extends DialogComponentProps {
tspClient: TspClient;
tspClient: ITspClient;
traceID: string;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { FrontendApplicationContribution } from '@theia/core/lib/browser';
import { inject, injectable } from 'inversify';
import { PortPreferenceProxy } from '../common/trace-server-url-provider';
import { TracePreferences, TRACE_PORT } from './trace-server-preference';

@injectable()
export class PreferencesFrontendContribution implements FrontendApplicationContribution {
constructor(
@inject(TracePreferences) protected tracePreferences: TracePreferences,
@inject(PortPreferenceProxy) protected portPreferenceProxy: PortPreferenceProxy
) {}

async initialize(): Promise<void> {
this.tracePreferences.ready.then(() => {
this.portPreferenceProxy.onPortPreferenceChanged(this.tracePreferences[TRACE_PORT]);
this.tracePreferences.onPreferenceChanged(async event => {
if (event.preferenceName === TRACE_PORT) {
const newValue = typeof event.newValue === 'string' ? parseInt(event.newValue) : event.newValue;
const oldValue = typeof event.oldValue === 'string' ? parseInt(event.oldValue) : event.oldValue;
this.portPreferenceProxy.onPortPreferenceChanged(newValue, oldValue, true);
}
});
});
}
}
Loading

0 comments on commit a1d5a0c

Please sign in to comment.