Skip to content

Commit 651f830

Browse files
authored
feat: support data centers (#1091)
* feat: support data centers * improve offer info * improve cc epochs display * gen manifest if it doesn't exist * fix data center is optional * Apply automatic changes * fix init * add peerId comment * use peerId base58 * rename to cityIndex * use latest snapshot --------- Co-authored-by: shamsartem <[email protected]>
1 parent 26dd8b7 commit 651f830

File tree

11 files changed

+282
-36
lines changed

11 files changed

+282
-36
lines changed

packages/cli/package/docs/configs/provider.md

+13-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Defines provider configuration
88
|-----------------------|--------------------------------|----------|----------------------------------------------------------------------------|
99
| `capacityCommitments` | [object](#capacitycommitments) | **Yes** | A map with computePeer names as keys and capacity commitments as values |
1010
| `computePeers` | [object](#computepeers) | **Yes** | A map with compute peer names as keys and compute peer configs as values |
11+
| `dataCenters` | [object](#datacenters) | **Yes** | A map with data center names as keys and data center IDs as values |
1112
| `offers` | [object](#offers) | **Yes** | A map with offer names as keys and offer configs as values |
1213
| `providerName` | string | **Yes** | Provider name. Must not be empty |
1314
| `version` | integer | **Yes** | Config version |
@@ -170,6 +171,16 @@ Override or extend Storage details not related to matching but visible to the us
170171
| `model` | string | No | |
171172
| `sequentialWriteSpeed` | integer | No | |
172173

174+
## dataCenters
175+
176+
A map with data center names as keys and data center IDs as values
177+
178+
### Properties
179+
180+
| Property | Type | Required | Description |
181+
|--------------------|--------|----------|-------------|
182+
| `<dataCenterName>` | string | No | |
183+
173184
## offers
174185

175186
A map with offer names as keys and offer configs as values
@@ -189,9 +200,10 @@ Defines a provider offer
189200
| Property | Type | Required | Description |
190201
|----------------------|---------------------------|----------|------------------------------------------------------------------------------------|
191202
| `computePeers` | string[] | **Yes** | Compute peers participating in this offer |
203+
| `dataCenterName` | string | **Yes** | Data center name from top-level dataCenters property |
204+
| `resourcePrices` | [object](#resourceprices) | **Yes** | Resource prices for the offer |
192205
| `maxProtocolVersion` | integer | No | Max protocol version. Must be more then or equal to minProtocolVersion. Default: 1 |
193206
| `minProtocolVersion` | integer | No | Min protocol version. Must be less then or equal to maxProtocolVersion. Default: 1 |
194-
| `resourcePrices` | [object](#resourceprices) | No | Resource prices for the offer |
195207

196208
#### resourcePrices
197209

packages/cli/package/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
"whatwg-url": "^14.0.0"
5757
},
5858
"dependencies": {
59-
"@fluencelabs/deal-ts-clients": "0.23.2-feat-marketplace-v2-resources-03f7996-7429-1.0",
59+
"@fluencelabs/deal-ts-clients": "0.23.2-add-dc-to-subgraph-afdd94a-7473-1.0",
6060
"@kubernetes/client-node": "github:fluencelabs/kubernetes-client-javascript#e72ee00a52fec4eb4a8327632895d888ee504f4d",
6161
"@libp2p/crypto": "4.0.1",
6262
"@libp2p/peer-id-factory": "4.0.5",

packages/cli/package/src/lib/chain/commitment.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -1027,9 +1027,10 @@ async function getDetailedCommitmentInfo({
10271027
"@fluencelabs/deal-ts-clients/dist/dealExplorerClient/utils.js"
10281028
);
10291029

1030+
const isCCNotStarted = ccFromChain.startEpoch === 0n;
1031+
10301032
function getStartOrExpirationDate(epoch: bigint) {
1031-
// if startEpoch is 0, then it's not yet started - no need to show anything
1032-
return ccFromChain.startEpoch === 0n
1033+
return isCCNotStarted
10331034
? "-"
10341035
: secondsToDate(
10351036
calculateTimestamp(
@@ -1077,8 +1078,9 @@ async function getDetailedCommitmentInfo({
10771078
ccFromChain.rewardDelegatorRate,
10781079
precision,
10791080
),
1080-
startEpoch: bigintToStr(ccFromChain.startEpoch),
1081-
endEpoch: bigintToStr(ccFromChain.endEpoch),
1081+
durationEpochs: bigintToStr(ccFromChain.endEpoch - ccFromChain.startEpoch),
1082+
startEpoch: isCCNotStarted ? "-" : bigintToStr(ccFromChain.startEpoch),
1083+
endEpoch: isCCNotStarted ? "-" : bigintToStr(ccFromChain.endEpoch),
10821084
currentEpoch: bigintToStr(currentEpoch),
10831085
startDate: getStartOrExpirationDate(ccFromChain.startEpoch),
10841086
expirationDate: getStartOrExpirationDate(ccFromChain.endEpoch),
@@ -1125,6 +1127,7 @@ function getDetailedCommitmentInfoString(
11251127
Status: detailedCommitmentInfo.status,
11261128
Staker: detailedCommitmentInfo.staker,
11271129
"Staker reward": detailedCommitmentInfo.stakerReward,
1130+
"Duration (epochs)": detailedCommitmentInfo.durationEpochs,
11281131
"Start / End / Current epoch": [
11291132
detailedCommitmentInfo.startEpoch,
11301133
detailedCommitmentInfo.endEpoch,

packages/cli/package/src/lib/chain/offer/offer.ts

+35-1
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ export async function createOffers(flags: OffersArgs) {
138138
computePeersFromProviderConfig: allCPs,
139139
offerName,
140140
resourcePricesWithIds,
141+
dataCenter,
141142
} = offer;
142143

143144
const resourcePricesArray = Object.values({
@@ -168,6 +169,7 @@ export async function createOffers(flags: OffersArgs) {
168169
contracts.deployment.usdc,
169170
resourcePricesArray,
170171
setCPUSupplyForCP(computePeersToRegister),
172+
dataCenter.id,
171173
];
172174
},
173175
getTitle() {
@@ -361,6 +363,7 @@ async function confirmOffer(offer: EnsureOfferConfig) {
361363
"",
362364
{},
363365
{
366+
"Data Center": offer.dataCenter,
364367
"Resource Prices": {
365368
CPU: await formatOfferResourcePrice("cpu", offer),
366369
RAM: await formatOfferResourcePrice("ram", offer),
@@ -456,6 +459,7 @@ export async function addRemainingCPs({
456459
}) {
457460
const { contracts } = await getContracts();
458461
let totalAddedCPs = addedCPs.length;
462+
const addedCPsNames = [];
459463

460464
while (totalAddedCPs < allCPs.length) {
461465
const remainingCPs = allCPs.slice(totalAddedCPs);
@@ -487,8 +491,16 @@ export async function addRemainingCPs({
487491
offerName,
488492
});
489493

494+
addedCPsNames.push(
495+
...addedCPs.map(({ name }) => {
496+
return name;
497+
}),
498+
);
499+
490500
totalAddedCPs = totalAddedCPs + addedCPs.length;
491501
}
502+
503+
return { addedCPsNames };
492504
}
493505

494506
async function addRemainingCUs({
@@ -617,6 +629,7 @@ async function formatOfferInfo(
617629
{
618630
"Provider ID": offerIndexerInfo.providerId,
619631
"Offer ID": offerIndexerInfo.id,
632+
"Data Center": offerIndexerInfo.dataCenter,
620633
"Created At": offerIndexerInfo.createdAt,
621634
"Last Updated At": offerIndexerInfo.updatedAt,
622635
"Resource Prices": offerIndexerInfo.resources?.map(
@@ -828,10 +841,21 @@ export async function resolveOffersFromProviderConfig(
828841
),
829842
);
830843

844+
const { dataCenter } = offerIndexerInfo;
845+
846+
assert(
847+
dataCenter !== null && dataCenter !== undefined,
848+
"Data center is always saved for offer on-chain when offer is created. Try waiting for indexer to index the data center",
849+
);
850+
851+
const { id: dataCenterId } = dataCenter;
852+
assertIsHex(dataCenterId, "Data center ID must be a hex string");
853+
831854
return {
832855
offerName: `Offer ${offerId}`,
833856
computePeersFromProviderConfig,
834857
offerId,
858+
dataCenter: { id: dataCenterId, name: dataCenterId },
835859
minProtocolVersion: Number(
836860
protocolVersionsFromChain.minProtocolVersion,
837861
),
@@ -954,6 +978,7 @@ async function ensureOfferConfigs() {
954978
minProtocolVersion,
955979
maxProtocolVersion,
956980
resourcePrices,
981+
dataCenterName,
957982
},
958983
]) => {
959984
const computePeerConfigs = await ensureComputerPeerConfigs({
@@ -1073,14 +1098,22 @@ async function ensureOfferConfigs() {
10731098
bandwidth: await getResourcePricesWithIds("bandwidth"),
10741099
};
10751100

1101+
const dataCenterId = providerConfig.dataCenters[dataCenterName];
1102+
1103+
assert(
1104+
dataCenterId !== undefined,
1105+
`Unreachable. Data center ${dataCenterName} is not found in provider config. This must be validated during config validation`,
1106+
);
1107+
10761108
return {
10771109
offerName,
10781110
computePeersFromProviderConfig,
10791111
offerId,
10801112
minProtocolVersion,
10811113
maxProtocolVersion,
10821114
resourcePricesWithIds,
1083-
};
1115+
dataCenter: { name: dataCenterName, id: `0x${dataCenterId}` },
1116+
} as const;
10841117
},
10851118
),
10861119
);
@@ -1362,6 +1395,7 @@ function serializeOfferInfo(offerIndexerInfo: OfferIndexerInfo) {
13621395

13631396
return {
13641397
id: offerIndexerInfo.id,
1398+
dataCenter: offerIndexerInfo.datacenter,
13651399
createdAt: new Date(
13661400
Number(offerIndexerInfo.createdAt) * 1000,
13671401
).toISOString(),

packages/cli/package/src/lib/chain/offer/updateOffers.ts

+61-7
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import { color } from "@oclif/color";
1919
import omit from "lodash-es/omit.js";
20+
import { stringify } from "yaml";
2021

2122
import { commandObj } from "../../commandObj.js";
2223
import type { ResourceType } from "../../configs/project/provider/provider4.js";
@@ -31,6 +32,7 @@ import { numToStr } from "../../helpers/typesafeStringify.js";
3132
import { splitErrorsAndResults } from "../../helpers/utils.js";
3233
import { confirm } from "../../prompt.js";
3334
import { ensureFluenceEnv } from "../../resolveFluenceEnv.js";
35+
import type { Required } from "../../typeHelpers.js";
3436
import { uint8ArrayToPeerIdHexString } from "../conversions.js";
3537
import {
3638
peerIdHexStringToBase58String,
@@ -58,7 +60,9 @@ type PeersOnChain = {
5860
hexPeerId: string;
5961
}[];
6062

61-
type Txs = { description?: string; tx: ReturnType<typeof populateTx> }[];
63+
type Tx = { description?: string; tx: ReturnType<typeof populateTx> };
64+
type Txs = Tx[];
65+
type TxsWithDescription = Required<Tx>[];
6266

6367
export async function updateOffers(flags: OffersArgs) {
6468
const offers = await resolveOffersFromProviderConfig(flags);
@@ -79,7 +83,25 @@ export async function updateOffers(flags: OffersArgs) {
7983
].flat();
8084

8185
if (firstUpdateOffersTx === undefined) {
82-
commandObj.logToStderr("No changes found for selected offers");
86+
const addedCPs = populatedTxs.reduce<Record<string, string[]>>(
87+
(acc, { addedCPsNames, offerName }) => {
88+
if (addedCPsNames.length > 0) {
89+
acc[offerName] = addedCPsNames;
90+
}
91+
92+
return acc;
93+
},
94+
{},
95+
);
96+
97+
if (Object.values(addedCPs).length === 0) {
98+
commandObj.logToStderr("No changes found for selected offers");
99+
} else {
100+
commandObj.logToStderr(
101+
`Added the compute peers to the following offers:\n${stringify(addedCPs)}`,
102+
);
103+
}
104+
83105
return;
84106
}
85107

@@ -229,10 +251,14 @@ function populateUpdateOffersTxs(offersFoundOnChain: OnChainOffer[]) {
229251
peersOnChain,
230252
)) satisfies Txs;
231253

232-
await addMissingComputePeers(offer, peersOnChain);
254+
const { addedCPsNames } = await addMissingComputePeers(
255+
offer,
256+
peersOnChain,
257+
);
233258

234259
const txs = (
235260
await Promise.all([
261+
populateDataCenterTx(offer),
236262
populateChangeResourceSupplyAndDetailsTx(offer),
237263
populateCUToRemoveTxs(offer, peersOnChain),
238264
populateCUToAddTxs(offer, peersOnChain),
@@ -244,7 +270,13 @@ function populateUpdateOffersTxs(offersFoundOnChain: OnChainOffer[]) {
244270
])
245271
).flat() satisfies Txs;
246272

247-
return { offerName, offerId, removePeersFromOffersTxs, txs };
273+
return {
274+
offerName,
275+
offerId,
276+
removePeersFromOffersTxs,
277+
txs,
278+
addedCPsNames,
279+
};
248280
}),
249281
);
250282
}
@@ -344,6 +376,28 @@ async function populatePaymentTokenTx({
344376
];
345377
}
346378

379+
async function populateDataCenterTx({
380+
offerIndexerInfo,
381+
offerId,
382+
dataCenter,
383+
}: OnChainOffer) {
384+
const { contracts } = await getContracts();
385+
return offerIndexerInfo.dataCenter?.id === dataCenter.id
386+
? []
387+
: [
388+
{
389+
description: `\nchanging data center from ${color.yellow(
390+
offerIndexerInfo.dataCenter?.id,
391+
)} to ${color.yellow(dataCenter.id)}`,
392+
tx: populateTx(
393+
contracts.diamond.setOfferDatacenter,
394+
offerId,
395+
dataCenter.id,
396+
),
397+
},
398+
];
399+
}
400+
347401
async function populateCUToRemoveTxs(
348402
{ computePeersFromProviderConfig }: OnChainOffer,
349403
peersOnChain: PeersOnChain,
@@ -492,7 +546,7 @@ async function createResourceSupplyAndDetailsUpdateTx(
492546
peerId: string,
493547
{ resourceType, onChainResource, configuredResource }: ResourceSupplyUpdate,
494548
) {
495-
const txs: { description: string; tx: ReturnType<typeof populateTx> }[] = [];
549+
const txs: TxsWithDescription = [];
496550

497551
if (onChainResource.resourceId !== configuredResource.resourceId) {
498552
return txs;
@@ -548,7 +602,7 @@ async function populateChangeResourceSupplyAndDetailsTx({
548602
computePeersFromProviderConfig,
549603
offerIndexerInfo,
550604
}: OnChainOffer) {
551-
const txs: { description?: string; tx: ReturnType<typeof populateTx> }[] = [];
605+
const txs: Txs = [];
552606

553607
for (const peer of offerIndexerInfo.peers) {
554608
const peerIdBase58 = await peerIdHexStringToBase58String(peer.id);
@@ -638,7 +692,7 @@ async function createResourceUpdateTx(
638692
peerId: string,
639693
{ resourceType, onChainResource, configuredResource }: ResourceUpdate,
640694
) {
641-
const txs: { description: string; tx: ReturnType<typeof populateTx> }[] = [];
695+
const txs: TxsWithDescription = [];
642696
const { contracts } = await getContracts();
643697

644698
function removeResource() {

0 commit comments

Comments
 (0)