Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const attributeSchemaType = z.object({
export const ProviderAttributesSchemaResponseSchema = z.object({
host: attributeSchemaType,
email: attributeSchemaType,
"discord-username": attributeSchemaType,
organization: attributeSchemaType,
website: attributeSchemaType,
tier: attributeSchemaType,
Expand All @@ -34,15 +35,18 @@ export const ProviderAttributesSchemaResponseSchema = z.object({
"hardware-cpu-arch": attributeSchemaType,
"hardware-gpu": attributeSchemaType,
"hardware-gpu-model": attributeSchemaType,
"hardware-disk": attributeSchemaType,
"hardware-gpu-capability": attributeSchemaType,
"hardware-persistent-storage-class": attributeSchemaType,
"hardware-persistent-storage-capability": attributeSchemaType,
"hardware-cuda": attributeSchemaType,
datacenter: attributeSchemaType,
"hardware-memory": attributeSchemaType,
"network-provider": attributeSchemaType,
"network-speed-up": attributeSchemaType,
"network-speed-down": attributeSchemaType,
"feat-persistent-storage": attributeSchemaType,
"feat-persistent-storage-type": attributeSchemaType,
"workload-support-chia": attributeSchemaType,
"workload-support-chia-capabilities": attributeSchemaType,
"feat-shm": attributeSchemaType,
"hardware-shm": attributeSchemaType,
"feat-endpoint-ip": attributeSchemaType,
"feat-endpoint-custom-domain": attributeSchemaType
});
Expand Down
20 changes: 12 additions & 8 deletions apps/api/src/provider/http-schemas/provider.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,17 +73,19 @@ export const ProviderListResponseSchema = z.array(
hardwareCpuArch: z.string().nullable(),
hardwareGpuVendor: z.string().nullable(),
hardwareGpuModels: z.array(z.string()).nullable(),
hardwareDisk: z.array(z.string()).nullable(),
hardwareGpuCapabilities: z.array(z.string()).nullable(),
hardwarePersistentStorageClass: z.string().nullable(),
featPersistentStorage: z.boolean(),
featPersistentStorageType: z.array(z.string()).nullable(),
featShm: z.boolean(),
hardwareShm: z.array(z.string()).nullable(),
hardwareCuda: z.string().nullable(),
datacenter: z.string().nullable(),
hardwareMemory: z.string().nullable(),
networkProvider: z.string().nullable(),
networkSpeedDown: z.number(),
networkSpeedUp: z.number(),
tier: z.string().nullable(),
featEndpointCustomDomain: z.boolean(),
workloadSupportChia: z.boolean(),
workloadSupportChiaCapabilities: z.array(z.string()).nullable(),
featEndpointIp: z.boolean()
})
);
Expand Down Expand Up @@ -163,17 +165,19 @@ export const ProviderResponseSchema = z.object({
hardwareCpuArch: z.string().nullable(),
hardwareGpuVendor: z.string().nullable(),
hardwareGpuModels: z.array(z.string()),
hardwareDisk: z.array(z.string()),
hardwareGpuCapabilities: z.array(z.string()),
hardwarePersistentStorageClass: z.string().nullable(),
featPersistentStorage: z.boolean(),
featPersistentStorageType: z.array(z.string()),
featShm: z.boolean(),
hardwareShm: z.array(z.string()),
hardwareCuda: z.string().nullable(),
datacenter: z.string().nullable(),
hardwareMemory: z.string().nullable(),
networkProvider: z.string().nullable(),
networkSpeedDown: z.number(),
networkSpeedUp: z.number(),
tier: z.string().nullable(),
featEndpointCustomDomain: z.boolean(),
workloadSupportChia: z.boolean(),
workloadSupportChiaCapabilities: z.array(z.string()),
featEndpointIp: z.boolean(),
uptime: z.array(
z.object({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { GitHubHttpService } from "@akashnetwork/http-sdk";
import { GitHubHttpService, type ProviderAttributesSchema } from "@akashnetwork/http-sdk";
import { minutesToSeconds } from "date-fns";
import fs from "fs/promises";
import path from "path";
import { singleton } from "tsyringe";

import { Memoize } from "@src/caching/helpers";
Expand All @@ -9,7 +11,12 @@ export class ProviderAttributesSchemaService {
constructor(private readonly gitHubHttpService: GitHubHttpService) {}

@Memoize({ ttlInSeconds: minutesToSeconds(5) })
async getProviderAttributesSchema() {
async getProviderAttributesSchema(): Promise<ProviderAttributesSchema> {
if (process.env.DEPLOYMENT_ENV === "test") {
const schemaPath = path.join(__dirname, "../../../../../../config/provider-attributes.json");
return JSON.parse(await fs.readFile(schemaPath, "utf8")) as ProviderAttributesSchema;
}
Comment thread
Zblocker64 marked this conversation as resolved.
Outdated

return await this.gitHubHttpService.getProviderAttributesSchema();
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Provider } from "@akashnetwork/database/dbSchemas/akash";
import { ProviderAttribute } from "@akashnetwork/database/dbSchemas/akash";
import type { GitHubHttpService } from "@akashnetwork/http-sdk";
import type { GitHubHttpService, ProviderAttributesSchema } from "@akashnetwork/http-sdk";
import fs from "fs/promises";
import path from "path";
import { container } from "tsyringe";
Expand Down Expand Up @@ -50,8 +50,8 @@ describe("ProviderRegions", () => {
function setup() {
return new ProviderRegionsService(
new ProviderAttributesSchemaService({
async getProviderAttributesSchema() {
return JSON.parse(await fs.readFile(path.join(__dirname, "../../../../../../config/provider-attributes.json"), "utf8"));
async getProviderAttributesSchema(): Promise<ProviderAttributesSchema> {
return JSON.parse(await fs.readFile(path.join(__dirname, "../../../../../../config/provider-attributes.json"), "utf8")) as ProviderAttributesSchema;
}
} as unknown as GitHubHttpService)
);
Expand Down
12 changes: 8 additions & 4 deletions apps/api/src/provider/services/provider/provider.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const schemaDetail = { key: "test", type: "string" as const, required: false, de
const providerAttributeSchemaStub: ProviderAttributesSchema = {
host: schemaDetail,
email: schemaDetail,
"discord-username": schemaDetail,
organization: schemaDetail,
website: schemaDetail,
tier: schemaDetail,
Expand All @@ -37,15 +38,18 @@ const providerAttributeSchemaStub: ProviderAttributesSchema = {
"hardware-cpu-arch": schemaDetail,
"hardware-gpu": schemaDetail,
"hardware-gpu-model": schemaDetail,
"hardware-disk": schemaDetail,
"hardware-gpu-capability": schemaDetail,
"hardware-persistent-storage-class": schemaDetail,
"hardware-persistent-storage-capability": schemaDetail,
"hardware-cuda": schemaDetail,
datacenter: schemaDetail,
"hardware-memory": schemaDetail,
"network-provider": schemaDetail,
"network-speed-up": schemaDetail,
"network-speed-down": schemaDetail,
"feat-persistent-storage": schemaDetail,
"feat-persistent-storage-type": schemaDetail,
"workload-support-chia": schemaDetail,
"workload-support-chia-capabilities": schemaDetail,
"feat-shm": schemaDetail,
"hardware-shm": schemaDetail,
"feat-endpoint-ip": schemaDetail,
"feat-endpoint-custom-domain": schemaDetail
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,12 @@ export class ProviderService {
this.providerAttributesSchemaService.getProviderAttributesSchema()
]);

const mapped = mapProviderToList(provider, providerAttributeSchema, auditors, lastSuccessfulSnapshot ?? undefined);

return {
...mapProviderToList(provider, providerAttributeSchema, auditors, lastSuccessfulSnapshot ?? undefined),
...mapped,
hardwareGpuCapabilities: mapped.hardwareGpuCapabilities ?? [],
Comment thread
Zblocker64 marked this conversation as resolved.
hardwareShm: mapped.hardwareShm ?? [],
uptime: uptimeSnapshots.map(ps => ({
id: ps.id,
isOnline: ps.isOnline,
Expand Down
14 changes: 9 additions & 5 deletions apps/api/src/types/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,19 @@ export interface ProviderList {
hardwareCpuArch: string | null;
hardwareGpuVendor: string | null;
hardwareGpuModels: string[] | null;
hardwareDisk: string[] | null;
hardwareGpuCapabilities: string[] | null;
hardwarePersistentStorageClass: string | null;
featPersistentStorage: boolean;
featPersistentStorageType: string[] | null;
featShm: boolean;
hardwareShm: string[] | null;
hardwareCuda: string | null;
datacenter: string | null;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
hardwareMemory: string | null;
networkProvider: string | null;
networkSpeedDown: number;
networkSpeedUp: number;
tier: string | null;
featEndpointCustomDomain: boolean;
workloadSupportChia: boolean;
workloadSupportChiaCapabilities: string[] | null;
featEndpointIp: boolean;
}

Expand All @@ -75,7 +77,9 @@ export interface ProviderCapacityStats {
};
}

export interface ProviderDetail extends ProviderList {
export interface ProviderDetail extends Omit<ProviderList, "hardwareGpuCapabilities" | "hardwareShm"> {
hardwareGpuCapabilities: string[];
hardwareShm: string[];
uptime: {
id: string;
isOnline: boolean;
Expand Down
131 changes: 131 additions & 0 deletions apps/api/src/utils/map/provider.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
import type { Provider } from "@akashnetwork/database/dbSchemas/akash";
import type { ProviderAttributesSchema } from "@akashnetwork/http-sdk";
import { describe, expect, it } from "vitest";

import { createProviderSeed } from "../../../test/seeders/provider.seeder";
import { mapProviderToList } from "./provider";

const schemaDetail = { key: "test", type: "string" as const, required: false, description: "test", values: null };

const providerAttributeSchemaStub: ProviderAttributesSchema = {
Comment thread
Zblocker64 marked this conversation as resolved.
Outdated
host: { ...schemaDetail, key: "host" },
email: { ...schemaDetail, key: "email" },
"discord-username": { ...schemaDetail, key: "discord-username" },
organization: { ...schemaDetail, key: "organization" },
website: { ...schemaDetail, key: "website" },
tier: { ...schemaDetail, key: "tier" },
"status-page": { ...schemaDetail, key: "status-page" },
"location-region": { ...schemaDetail, key: "location-region", type: "option" },
country: { ...schemaDetail, key: "country" },
city: { ...schemaDetail, key: "city" },
timezone: { ...schemaDetail, key: "timezone" },
"location-type": { ...schemaDetail, key: "location-type" },
"hosting-provider": { ...schemaDetail, key: "hosting-provider" },
"hardware-cpu": { ...schemaDetail, key: "hardware-cpu" },
"hardware-cpu-arch": { ...schemaDetail, key: "hardware-cpu-arch" },
"hardware-gpu": { ...schemaDetail, key: "hardware-gpu" },
"hardware-gpu-model": { ...schemaDetail, key: "hardware-gpu-model", type: "multiple-option" },
"hardware-gpu-capability": { ...schemaDetail, key: "hardware-gpu-capability", type: "multiple-option" },
"hardware-persistent-storage-class": { ...schemaDetail, key: "hardware-persistent-storage-class", type: "option" },
"hardware-persistent-storage-capability": { ...schemaDetail, key: "hardware-persistent-storage-capability", type: "boolean" },
"hardware-cuda": { ...schemaDetail, key: "hardware-cuda" },
datacenter: { ...schemaDetail, key: "datacenter" },
"hardware-memory": { ...schemaDetail, key: "hardware-memory" },
"network-provider": { ...schemaDetail, key: "network-provider" },
"network-speed-up": { ...schemaDetail, key: "network-speed-up", type: "number" },
"network-speed-down": { ...schemaDetail, key: "network-speed-down", type: "number" },
"feat-persistent-storage": { ...schemaDetail, key: "feat-persistent-storage", type: "boolean" },
"feat-shm": { ...schemaDetail, key: "feat-shm", type: "boolean" },
"hardware-shm": { ...schemaDetail, key: "hardware-shm", type: "multiple-option" },
"feat-endpoint-ip": { ...schemaDetail, key: "feat-endpoint-ip", type: "boolean" },
"feat-endpoint-custom-domain": { ...schemaDetail, key: "feat-endpoint-custom-domain", type: "boolean" }
};

function mapWithAttributes(attributes: Array<{ key: string; value: string }>) {
const provider = {
...createProviderSeed({ isOnline: true, cosmosSdkVersion: "v0.45.9" }),
providerAttributes: attributes,
providerAttributeSignatures: []
} as Provider;

return mapProviderToList(provider, providerAttributeSchemaStub, [], undefined);
}

describe(mapProviderToList.name, () => {
describe("locationRegion", () => {
it("prefers location-region over legacy region", () => {
const mapped = mapWithAttributes([
{ key: "location-region", value: "na-us-west" },
{ key: "region", value: "us-west" }
]);

expect(mapped.locationRegion).toBe("na-us-west");
});

it("falls back to legacy region when location-region is absent", () => {
const mapped = mapWithAttributes([{ key: "region", value: "us-west" }]);

expect(mapped.locationRegion).toBe("us-west");
});
});

describe("featShm", () => {
it("is true when feat-shm is true", () => {
const mapped = mapWithAttributes([{ key: "feat-shm", value: "true" }]);

expect(mapped.featShm).toBe(true);
});

it("is true when any storage class is ram", () => {
const mapped = mapWithAttributes([
{ key: "capabilities/storage/2/class", value: "ram" },
{ key: "capabilities/storage/2/persistent", value: "false" }
]);

expect(mapped.featShm).toBe(true);
});

it("is false when no shm signals are present", () => {
const mapped = mapWithAttributes([{ key: "capabilities/storage/1/class", value: "beta3" }]);

expect(mapped.featShm).toBe(false);
});
});

describe("featPersistentStorage", () => {
it("is true when feat-persistent-storage is true", () => {
const mapped = mapWithAttributes([{ key: "feat-persistent-storage", value: "true" }]);

expect(mapped.featPersistentStorage).toBe(true);
});

it("is true when hardware-persistent-storage-capability is true", () => {
const mapped = mapWithAttributes([{ key: "hardware-persistent-storage-capability", value: "true" }]);

expect(mapped.featPersistentStorage).toBe(true);
});

it("is true when capabilities/storage/1/persistent is true", () => {
const mapped = mapWithAttributes([{ key: "capabilities/storage/1/persistent", value: "true" }]);

expect(mapped.featPersistentStorage).toBe(true);
});

it("is true when persistent storage is declared on a non-default storage index", () => {
const mapped = mapWithAttributes([
{ key: "capabilities/storage/1/class", value: "beta3" },
{ key: "capabilities/storage/1/persistent", value: "false" },
{ key: "capabilities/storage/2/class", value: "beta2" },
{ key: "capabilities/storage/2/persistent", value: "true" }
]);

expect(mapped.featPersistentStorage).toBe(true);
});

it("is false when no persistent storage signals are present", () => {
const mapped = mapWithAttributes([{ key: "capabilities/storage/1/persistent", value: "false" }]);

expect(mapped.featPersistentStorage).toBe(false);
});
});
});
Loading
Loading