Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support load twin and fix type issue in load node byId in gridProxy client #1140

Merged
merged 2 commits into from
Sep 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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