Skip to content

Commit

Permalink
support load twin and fix type issue in load node byId in gridProxy c…
Browse files Browse the repository at this point in the history
…lient (#1140)

* Support load twin & fix type issue in load node byId

* Add load node stats
  • Loading branch information
MohamedElmdary authored Sep 25, 2023
1 parent 5fc1317 commit ceb8182
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 24 deletions.
4 changes: 2 additions & 2 deletions packages/gridproxy_client/src/modules/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ export default class GridProxyClient {
this.contracts = new ContractsClient(this.__uri);
this.farms = new FarmsClient(this.__uri);
this.gateways = new GatewaysClient(this.__uri);
this.nodes = new NodesClient(this.__uri, this.farms);
this.stats = new StatsClient(this.__uri);
this.twins = new TwinsClient(this.__uri);
this.nodes = new NodesClient(this.__uri, this.farms, this.twins);
this.stats = new StatsClient(this.__uri);
}

public contracts: ContractsClient;
Expand Down
15 changes: 14 additions & 1 deletion packages/gridproxy_client/src/modules/gateways.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { CertificationType, GatewayBuilder, GatewaysQuery, NodeStatus } from "../builders/public_api";
import { assertId, resolvePaginator } from "../utils";
import { AbstractClient } from "./abstract_client";
import { Farm } from "./farms";
import type { Farm } from "./farms";
import type { Twin } from "./twins";

export interface Resources {
cru: number;
Expand All @@ -27,6 +28,16 @@ export interface PublicIps {
free: number;
}

export interface NodeStats {
system: Resources & { ipv4u: number };
total: Resources & { ipv4u: number };
used: Resources & { ipv4u: number };
users: {
deployments: number;
workloads: number;
};
}

export interface GridNode {
id: string;
nodeId: number;
Expand All @@ -50,6 +61,8 @@ export interface GridNode {
rentedByTwinId: number;
farm: Farm;
publicIps: PublicIps;
twin: Twin;
stats: NodeStats;
}

export class GatewaysClient extends AbstractClient<GatewayBuilder, GatewaysQuery> {
Expand Down
86 changes: 66 additions & 20 deletions packages/gridproxy_client/src/modules/nodes.ts
Original file line number Diff line number Diff line change
@@ -1,68 +1,95 @@
import type { Pagination } from "../builders/abstract_builder";
import { NodesBuilder, type NodesQuery } from "../builders/nodes";
import { resolvePaginator } from "../utils";
import { AbstractClient } from "./abstract_client";
import type { Farm, FarmsClient } from "./farms";
import type { GridNode, PublicIps } from "./gateways";
import type { GridNode, NodeStats, PublicIps } from "./gateways";
import type { Twin, TwinsClient } from "./twins";

export interface NodesExtractOptions {
loadFarm?: boolean;
loadTwin?: boolean;
loadStats?: boolean;
}

export class NodesClient extends AbstractClient<NodesBuilder, NodesQuery> {
public farms: Map<number, Farm>;
public twins: Map<number, Twin>;

constructor(uri: string, private readonly __farmsClient: FarmsClient) {
constructor(uri: string, private readonly __farmsClient: FarmsClient, private readonly __twinsClient: TwinsClient) {
super({
uri,
Builder: NodesBuilder,
});

this.farms = new Map<number, Farm>();
this.setFarm = this.setFarm.bind(this);

this.twins = new Map<number, Twin>();
this.setTwin = this.setTwin.bind(this);
}

public async list(queries: Partial<NodesQuery> = {}, extraOptions: NodesExtractOptions = {}) {
const res = await this.builder(queries).build("/nodes");
const nodes = await resolvePaginator<GridNode[]>(res);

if (extraOptions.loadFarm) {
await this.loadFarms(nodes.data.map(n => n.farmId));
nodes.data = nodes.data.map(this.setFarm);
}

if (extraOptions.loadTwin) {
await this.loadTwins(nodes.data.map(n => n.twinId));
nodes.data = nodes.data.map(this.setTwin);
}

if (extraOptions.loadStats) {
const nodesStats = await Promise.all(nodes.data.map(n => this.statsById(n.nodeId)));
nodes.data = nodes.data.map((n, index) => {
n.stats = nodesStats[index];
return n;
});
}

return nodes;
}

public async byId(nodeId: number, extraOptions: NodesExtractOptions = {}): Promise<GridNode> {
const res = await this.builder({}).build(`/nodes/${nodeId}`);
const node = await res.json();
let node: GridNode = await res.json();

const capacity = Reflect.get(node, "capacity");
if (capacity) {
node.total_resources = Reflect.get(capacity, "total_resources");
node.used_resources = Reflect.get(capacity, "used_resources");
}

if (extraOptions.loadFarm && node) {
await this.loadFarms([node.farmId]);
return this.setFarm(node);
node = this.setFarm(node);
}

if (extraOptions.loadTwin) {
await this.loadTwins([node.twinId]);
node = this.setTwin(node);
}

if (extraOptions.loadStats) {
node.stats = await this.statsById(node.nodeId);
}

return node;
}

public async listAll(queries: Partial<NodesQuery> = {}) {
const { count } = await this.list({
...queries,
size: 50,
page: 1,
retCount: true,
});
const promises: Promise<Pagination<GridNode[]>>[] = [];
const pages = Math.ceil(count! / 50);
for (let i = 0; i < pages; i++) {
promises.push(this.list({ ...queries, size: 50, page: i + 1 }));
}
const nodes = await Promise.all(promises);
return nodes.map(node => node.data).flat(1);
public async statsById(nodeId: number): Promise<NodeStats> {
const res = await this.builder({}).build(`/nodes/${nodeId}/statistics`);
return res.json();
}

private async loadFarms(farmIds: number[]): Promise<void> {
farmIds = farmIds.filter(id => !this.farms.has(id));
const ids = Array.from(new Set(farmIds));
if (!ids.length) return;
const farms = await Promise.all(ids.map(id => this.__farmsClient.list({ farmId: id })));
const farms = await Promise.all(ids.map(farmId => this.__farmsClient.list({ farmId })));
for (const { data } of farms) {
const [farm] = data;
this.farms = this.farms.set(farm.farmId, farm);
Expand All @@ -87,4 +114,23 @@ export class NodesClient extends AbstractClient<NodesBuilder, NodesQuery> {
free,
};
}

private async loadTwins(twinIds: number[]): Promise<void> {
twinIds = twinIds.filter(id => !this.twins.has(id));
const ids = Array.from(new Set(twinIds));
if (!ids.length) return;
const twins = await Promise.all(ids.map(twinId => this.__twinsClient.list({ twinId })));
for (const { data } of twins) {
const [twin] = data;
this.twins = this.twins.set(twin.twinId, twin);
}
}

private setTwin(node: GridNode): GridNode {
const twin = this.twins.get(node.twinId);
if (twin) {
node.twin = twin;
}
return node;
}
}
3 changes: 2 additions & 1 deletion packages/gridproxy_client/src/modules/twins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { AbstractClient } from "./abstract_client";
export interface Twin {
twinId: number;
accountId: string;
ip: string;
relay: string;
publicKey: string;
}

export class TwinsClient extends AbstractClient<TwinsBuilder, TwinsQuery> {
Expand Down

0 comments on commit ceb8182

Please sign in to comment.