mirror of
https://github.com/pezkuwichain/pezkuwi-telemetry.git
synced 2026-06-13 01:01:02 +00:00
Subscribe to chains by genesis hash (#395)
* Handle subscription by hash in the frontend * Forward-ported backend changes * Fix unit tests * Remove unused `chains_by_label` * fmt * Updated but failing E2E tests * subscribe by genesis hash in tests * fmt * Copy `BlockHash` instead of returning a ref * Pin chains by genesisHash Co-authored-by: James Wilson <james@jsdw.me>
This commit is contained in:
@@ -228,7 +228,7 @@ export default class App extends React.Component<{}, {}> {
|
||||
this.chainsCache = stable.inplace(
|
||||
Array.from(this.appState.chains.values()),
|
||||
(a, b) => {
|
||||
const pinned = comparePinnedChains(a.label, b.label);
|
||||
const pinned = comparePinnedChains(a.genesisHash, b.genesisHash);
|
||||
|
||||
if (pinned !== 0) {
|
||||
return pinned;
|
||||
|
||||
@@ -119,7 +119,7 @@ export class Connection {
|
||||
// timestamp at which the last ping has been sent
|
||||
private pingSent: Maybe<Types.Timestamp> = null;
|
||||
// chain label to resubsribe to on reconnect
|
||||
private resubscribeTo: Maybe<Types.ChainLabel> = getHashData().chain;
|
||||
private resubscribeTo: Maybe<Types.GenesisHash> = getHashData().chain;
|
||||
// flag whether or not FE should subscribe to consensus updates on reconnect
|
||||
private resubscribeSendFinality: boolean = getHashData().tab === 'consensus';
|
||||
|
||||
@@ -132,7 +132,7 @@ export class Connection {
|
||||
this.bindSocket();
|
||||
}
|
||||
|
||||
public subscribe(chain: Types.ChainLabel) {
|
||||
public subscribe(chain: Types.GenesisHash) {
|
||||
if (
|
||||
this.appState.subscribed != null &&
|
||||
this.appState.subscribed !== chain
|
||||
@@ -148,7 +148,7 @@ export class Connection {
|
||||
this.socket.send(`subscribe:${chain}`);
|
||||
}
|
||||
|
||||
public subscribeConsensus(chain: Types.ChainLabel) {
|
||||
public subscribeConsensus(chain: Types.GenesisHash) {
|
||||
if (this.appState.authorities.length <= VIS_AUTHORITIES_LIMIT) {
|
||||
setHashData({ chain });
|
||||
this.resubscribeSendFinality = true;
|
||||
@@ -165,7 +165,7 @@ export class Connection {
|
||||
});
|
||||
}
|
||||
|
||||
public unsubscribeConsensus(chain: Types.ChainLabel) {
|
||||
public unsubscribeConsensus(chain: Types.GenesisHash) {
|
||||
this.resubscribeSendFinality = true;
|
||||
this.socket.send(`no-more-finality:${chain}`);
|
||||
}
|
||||
@@ -334,13 +334,13 @@ export class Connection {
|
||||
}
|
||||
|
||||
case ACTIONS.AddedChain: {
|
||||
const [label, nodeCount] = message.payload;
|
||||
const chain = chains.get(label);
|
||||
const [label, genesisHash, nodeCount] = message.payload;
|
||||
const chain = chains.get(genesisHash);
|
||||
|
||||
if (chain) {
|
||||
chain.nodeCount = nodeCount;
|
||||
} else {
|
||||
chains.set(label, { label, nodeCount });
|
||||
chains.set(genesisHash, { label, genesisHash, nodeCount });
|
||||
}
|
||||
|
||||
this.appUpdate({ chains });
|
||||
@@ -552,7 +552,7 @@ export class Connection {
|
||||
}
|
||||
|
||||
if (topChain) {
|
||||
this.subscribe(topChain.label);
|
||||
this.subscribe(topChain.genesisHash);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ import {
|
||||
Timestamp,
|
||||
Milliseconds,
|
||||
ChainLabel,
|
||||
GenesisHash,
|
||||
AuthoritySetInfo,
|
||||
} from './types';
|
||||
|
||||
@@ -142,22 +143,22 @@ export namespace Variants {
|
||||
|
||||
export interface AddedChainMessage extends MessageBase {
|
||||
action: typeof ACTIONS.AddedChain;
|
||||
payload: [ChainLabel, NodeCount];
|
||||
payload: [ChainLabel, GenesisHash, NodeCount];
|
||||
}
|
||||
|
||||
export interface RemovedChainMessage extends MessageBase {
|
||||
action: typeof ACTIONS.RemovedChain;
|
||||
payload: ChainLabel;
|
||||
payload: GenesisHash;
|
||||
}
|
||||
|
||||
export interface SubscribedToMessage extends MessageBase {
|
||||
action: typeof ACTIONS.SubscribedTo;
|
||||
payload: ChainLabel;
|
||||
payload: GenesisHash;
|
||||
}
|
||||
|
||||
export interface UnsubscribedFromMessage extends MessageBase {
|
||||
action: typeof ACTIONS.UnsubscribedFrom;
|
||||
payload: ChainLabel;
|
||||
payload: GenesisHash;
|
||||
}
|
||||
|
||||
export interface PongMessage extends MessageBase {
|
||||
|
||||
@@ -25,4 +25,4 @@ import * as FeedMessage from './feed';
|
||||
export { Types, FeedMessage };
|
||||
|
||||
// Increment this if breaking changes were made to types in `feed.ts`
|
||||
export const VERSION: Types.FeedVersion = 31 as Types.FeedVersion;
|
||||
export const VERSION: Types.FeedVersion = 32 as Types.FeedVersion;
|
||||
|
||||
@@ -19,6 +19,7 @@ import { Id } from './id';
|
||||
|
||||
export type FeedVersion = Opaque<number, 'FeedVersion'>;
|
||||
export type ChainLabel = Opaque<string, 'ChainLabel'>;
|
||||
export type GenesisHash = Opaque<string, 'GenesisHash'>;
|
||||
export type FeedId = Id<'Feed'>;
|
||||
export type NodeId = Id<'Node'>;
|
||||
export type NodeName = Opaque<string, 'NodeName'>;
|
||||
|
||||
@@ -24,7 +24,7 @@ import './AllChains.css';
|
||||
export namespace AllChains {
|
||||
export interface Props {
|
||||
chains: ChainData[];
|
||||
subscribed: Maybe<Types.ChainLabel>;
|
||||
subscribed: Maybe<Types.GenesisHash>;
|
||||
connection: Promise<Connection>;
|
||||
}
|
||||
}
|
||||
@@ -45,10 +45,10 @@ export class AllChains extends React.Component<AllChains.Props, {}> {
|
||||
}
|
||||
|
||||
private renderChain(chain: ChainData): React.ReactNode {
|
||||
const { label, nodeCount } = chain;
|
||||
const { label, genesisHash, nodeCount } = chain;
|
||||
|
||||
const className =
|
||||
label === this.props.subscribed
|
||||
genesisHash === this.props.subscribed
|
||||
? 'AllChains-chain AllChains-chain-selected'
|
||||
: 'AllChains-chain';
|
||||
|
||||
@@ -56,7 +56,7 @@ export class AllChains extends React.Component<AllChains.Props, {}> {
|
||||
<a
|
||||
key={label}
|
||||
className={className}
|
||||
onClick={this.subscribe.bind(this, label)}
|
||||
onClick={this.subscribe.bind(this, genesisHash)}
|
||||
>
|
||||
{label}{' '}
|
||||
<span className="AllChains-node-count" title="Node Count">
|
||||
@@ -66,7 +66,7 @@ export class AllChains extends React.Component<AllChains.Props, {}> {
|
||||
);
|
||||
}
|
||||
|
||||
private async subscribe(chain: Types.ChainLabel) {
|
||||
private async subscribe(chain: Types.GenesisHash) {
|
||||
const connection = await this.props.connection;
|
||||
|
||||
connection.subscribe(chain);
|
||||
|
||||
@@ -27,7 +27,7 @@ import './Chains.css';
|
||||
export namespace Chains {
|
||||
export interface Props {
|
||||
chains: ChainData[];
|
||||
subscribed: Maybe<Types.ChainLabel>;
|
||||
subscribed: Maybe<Types.GenesisHash>;
|
||||
connection: Promise<Connection>;
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ const RENDER_THROTTLE = 1000;
|
||||
|
||||
export class Chains extends React.Component<Chains.Props, {}> {
|
||||
private lastRender = performance.now();
|
||||
private clicked: Maybe<Types.ChainLabel>;
|
||||
private clicked: Maybe<Types.GenesisHash>;
|
||||
|
||||
public shouldComponentUpdate(nextProps: Chains.Props) {
|
||||
if (nextProps.subscribed !== this.clicked) {
|
||||
@@ -83,11 +83,11 @@ export class Chains extends React.Component<Chains.Props, {}> {
|
||||
}
|
||||
|
||||
private renderChain(chain: ChainData): React.ReactNode {
|
||||
const { label, nodeCount } = chain;
|
||||
const { label, genesisHash, nodeCount } = chain;
|
||||
|
||||
let className = 'Chains-chain';
|
||||
|
||||
if (label === this.props.subscribed) {
|
||||
if (genesisHash === this.props.subscribed) {
|
||||
className += ' Chains-chain-selected';
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ export class Chains extends React.Component<Chains.Props, {}> {
|
||||
<a
|
||||
key={label}
|
||||
className={className}
|
||||
onClick={this.subscribe.bind(this, label)}
|
||||
onClick={this.subscribe.bind(this, genesisHash)}
|
||||
>
|
||||
{label}
|
||||
<span className="Chains-node-count" title="Node Count">
|
||||
@@ -105,7 +105,7 @@ export class Chains extends React.Component<Chains.Props, {}> {
|
||||
);
|
||||
}
|
||||
|
||||
private async subscribe(chain: Types.ChainLabel) {
|
||||
private async subscribe(chain: Types.GenesisHash) {
|
||||
if (chain === this.clicked) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -427,12 +427,12 @@ export class Consensus extends React.Component<Consensus.Props, {}> {
|
||||
);
|
||||
}
|
||||
|
||||
private async subscribeConsensus(chain: Types.ChainLabel) {
|
||||
private async subscribeConsensus(chain: Types.GenesisHash) {
|
||||
const connection = await this.props.connection;
|
||||
connection.subscribeConsensus(chain);
|
||||
}
|
||||
|
||||
private async unsubscribeConsensus(chain: Types.ChainLabel) {
|
||||
private async unsubscribeConsensus(chain: Types.GenesisHash) {
|
||||
const connection = await this.props.connection;
|
||||
connection.unsubscribeConsensus(chain);
|
||||
}
|
||||
|
||||
@@ -19,8 +19,10 @@ import { Types, Maybe, SortedCollection } from './common';
|
||||
import { Column } from './components/List';
|
||||
|
||||
export const PINNED_CHAINS = {
|
||||
Kusama: 2,
|
||||
Polkadot: 1,
|
||||
// Kusama
|
||||
'0xb0a8d493285c2df73290dfb7e61f870f17b41801197a149ca93654499ea3dafe': 2,
|
||||
// Polkadot
|
||||
'0x91b171bb158e2d3848fa23a9f1c25182fb8e20313b2c1eb49219da7a70ce90c3': 1,
|
||||
};
|
||||
|
||||
export function comparePinnedChains(a: string, b: string) {
|
||||
@@ -275,8 +277,8 @@ export interface State {
|
||||
blockTimestamp: Types.Timestamp;
|
||||
blockAverage: Maybe<Types.Milliseconds>;
|
||||
timeDiff: Types.Milliseconds;
|
||||
subscribed: Maybe<Types.ChainLabel>;
|
||||
chains: Map<Types.ChainLabel, ChainData>;
|
||||
subscribed: Maybe<Types.GenesisHash>;
|
||||
chains: Map<Types.GenesisHash, ChainData>;
|
||||
nodes: SortedCollection<Node>;
|
||||
settings: Readonly<State.Settings>;
|
||||
pins: Readonly<Set<Types.NodeName>>;
|
||||
@@ -290,5 +292,6 @@ export type Update = <K extends keyof State>(
|
||||
|
||||
export interface ChainData {
|
||||
label: Types.ChainLabel;
|
||||
genesisHash: Types.GenesisHash;
|
||||
nodeCount: Types.NodeCount;
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ export function secondsWithPrecision(num: number): string {
|
||||
|
||||
export interface HashData {
|
||||
tab?: string;
|
||||
chain?: Types.ChainLabel;
|
||||
chain?: Types.GenesisHash;
|
||||
}
|
||||
|
||||
export function getHashData(): HashData {
|
||||
@@ -99,7 +99,7 @@ export function getHashData(): HashData {
|
||||
}
|
||||
|
||||
const [tab, rawChain] = hash.substr(1).split('/');
|
||||
const chain = decodeURIComponent(rawChain) as Types.ChainLabel;
|
||||
const chain = decodeURIComponent(rawChain) as Types.GenesisHash;
|
||||
|
||||
return { tab, chain };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user