@aztec/blob-client 0.0.1-commit.cbf2c2d5d → 0.0.1-commit.ce4f8c4f2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dest/client/http.d.ts +1 -1
- package/dest/client/http.d.ts.map +1 -1
- package/dest/client/http.js +48 -14
- package/package.json +7 -7
- package/src/client/http.ts +50 -14
package/dest/client/http.d.ts
CHANGED
|
@@ -82,4 +82,4 @@ export declare class HttpBlobClient implements BlobClientInterface {
|
|
|
82
82
|
*/
|
|
83
83
|
stop(): void;
|
|
84
84
|
}
|
|
85
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
85
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaHR0cC5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NsaWVudC9odHRwLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxJQUFJLEVBQUUsS0FBSyxRQUFRLEVBQStCLE1BQU0saUJBQWlCLENBQUM7QUFHbkYsT0FBTyxFQUFFLEtBQUssTUFBTSxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBT2xFLE9BQU8sS0FBSyxFQUFFLGlCQUFpQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDakUsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSx1Q0FBdUMsQ0FBQztBQUVqRixPQUFPLEVBQUUsS0FBSyxnQkFBZ0IsRUFBOEIsTUFBTSxhQUFhLENBQUM7QUFDaEYsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUscUJBQXFCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVqRixxQkFBYSxjQUFlLFlBQVcsbUJBQW1CO0lBa0J0RCxPQUFPLENBQUMsUUFBUSxDQUFDLElBQUk7SUFqQnZCLFNBQVMsQ0FBQyxRQUFRLENBQUMsR0FBRyxFQUFFLE1BQU0sQ0FBQztJQUMvQixTQUFTLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxnQkFBZ0IsQ0FBQztJQUM1QyxTQUFTLENBQUMsUUFBUSxDQUFDLGFBQWEsRUFBRSxpQkFBaUIsR0FBRyxTQUFTLENBQUM7SUFDaEUsU0FBUyxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsT0FBTyxLQUFLLENBQUM7SUFDdkMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxnQkFBZ0IsRUFBRSxtQkFBbUIsRUFBRSxDQUFDO0lBQzNELFNBQVMsQ0FBQyxRQUFRLENBQUMscUJBQXFCLEVBQUUsbUJBQW1CLEdBQUcsU0FBUyxDQUFDO0lBRTFFLE9BQU8sQ0FBQyxRQUFRLENBQVM7SUFDekIsT0FBTyxDQUFDLDJCQUEyQixDQUFDLENBQWlCO0lBRXJELHNGQUFzRjtJQUN0RixPQUFPLENBQUMsaUJBQWlCLENBQUMsQ0FBUztJQUNuQyx1RUFBdUU7SUFDdkUsT0FBTyxDQUFDLG9CQUFvQixDQUFDLENBQVM7SUFFdEMsWUFDRSxNQUFNLENBQUMsRUFBRSxnQkFBZ0IsRUFDUixJQUFJLEdBQUU7UUFDckIsTUFBTSxDQUFDLEVBQUUsTUFBTSxDQUFDO1FBQ2hCLGFBQWEsQ0FBQyxFQUFFLGlCQUFpQixDQUFDO1FBQ2xDLGdCQUFnQixDQUFDLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQztRQUN6QyxxQkFBcUIsQ0FBQyxFQUFFLG1CQUFtQixDQUFDO1FBQzVDLHlFQUF5RTtRQUN6RSxjQUFjLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsS0FBSyxJQUFJLENBQUM7S0FDckMsRUF3QlA7SUFFRDs7O09BR0c7SUFDSCxPQUFPLENBQUMsc0JBQXNCO0lBVTlCOzs7OztPQUtHO0lBQ0ksV0FBVyxDQUFDLEtBQUssRUFBRSxPQUFPLEdBQUcsSUFBSSxDQUd2QztJQUVZLFdBQVcsa0JBd0d2QjtJQUVZLG9CQUFvQixDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBbUJqRTtJQUVEOzs7Ozs7Ozs7Ozs7OztPQWNHO0lBQ1UsY0FBYyxDQUN6QixTQUFTLEVBQUUsS0FBSyxNQUFNLEVBQUUsRUFDeEIsVUFBVSxFQUFFLE1BQU0sRUFBRSxFQUNwQixJQUFJLENBQUMsRUFBRSxxQkFBcUIsR0FDM0IsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLENBa0pqQjtZQVFhLGFBQWE7SUFzQ2Qsa0JBQWtCLENBQzdCLE9BQU8sRUFBRSxNQUFNLEVBQ2YsZUFBZSxFQUFFLE1BQU0sR0FBRyxNQUFNLEVBQ2hDLFVBQVUsR0FBRSxNQUFNLEVBQU8sRUFDekIsb0JBQW9CLENBQUMsRUFBRSxNQUFNLEdBQzVCLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUdqQjtJQUVZLGdCQUFnQixDQUMzQixPQUFPLEVBQUUsTUFBTSxFQUNmLGVBQWUsRUFBRSxNQUFNLEdBQUcsTUFBTSxFQUNoQyxvQkFBb0IsQ0FBQyxFQUFFLE1BQU0sRUFDN0IsVUFBVSxDQUFDLEVBQUUsTUFBTSxFQUFFLEdBQ3BCLE9BQU8sQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQXNDckI7SUFFRCxPQUFPLENBQUMsaUJBQWlCO1lBcUJYLG1CQUFtQjtZQW1DbkIsYUFBYTtJQTZFM0Isc0NBQXNDO0lBQy9CLGdCQUFnQixJQUFJLGlCQUFpQixHQUFHLFNBQVMsQ0FFdkQ7SUFFRCxpRUFBaUU7SUFDMUQsU0FBUyxJQUFJLE9BQU8sQ0FFMUI7SUFFRDs7OztPQUlHO0lBQ1UsS0FBSyxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FXbEM7SUFFRDs7T0FFRztJQUNILE9BQU8sQ0FBQyw4QkFBOEI7WUFnQnhCLGlCQUFpQjtJQTBDL0I7O09BRUc7SUFDSSxJQUFJLElBQUksSUFBSSxDQUtsQjtDQUNGIn0=
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/client/http.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,QAAQ,EAA+B,MAAM,iBAAiB,CAAC;AAGnF,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAOlE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAEjF,OAAO,EAAE,KAAK,gBAAgB,EAA8B,MAAM,aAAa,CAAC;AAChF,OAAO,KAAK,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAEjF,qBAAa,cAAe,YAAW,mBAAmB;IAkBtD,OAAO,CAAC,QAAQ,CAAC,IAAI;IAjBvB,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IAC/B,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAC5C,SAAS,CAAC,QAAQ,CAAC,aAAa,EAAE,iBAAiB,GAAG,SAAS,CAAC;IAChE,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,KAAK,CAAC;IACvC,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,mBAAmB,EAAE,CAAC;IAC3D,SAAS,CAAC,QAAQ,CAAC,qBAAqB,EAAE,mBAAmB,GAAG,SAAS,CAAC;IAE1E,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,2BAA2B,CAAC,CAAiB;IAErD,sFAAsF;IACtF,OAAO,CAAC,iBAAiB,CAAC,CAAS;IACnC,uEAAuE;IACvE,OAAO,CAAC,oBAAoB,CAAC,CAAS;IAEtC,YACE,MAAM,CAAC,EAAE,gBAAgB,EACR,IAAI,GAAE;QACrB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,aAAa,CAAC,EAAE,iBAAiB,CAAC;QAClC,gBAAgB,CAAC,EAAE,mBAAmB,EAAE,CAAC;QACzC,qBAAqB,CAAC,EAAE,mBAAmB,CAAC;QAC5C,yEAAyE;QACzE,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;KACrC,EAwBP;IAED;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAU9B;;;;;OAKG;IACI,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAGvC;IAEY,WAAW,
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/client/http.ts"],"names":[],"mappings":"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"}
|
package/dest/client/http.js
CHANGED
|
@@ -69,22 +69,50 @@ export class HttpBlobClient {
|
|
|
69
69
|
l1ConsensusHostUrls,
|
|
70
70
|
archiveUrl
|
|
71
71
|
});
|
|
72
|
-
let
|
|
72
|
+
let consensusSuperNodes = 0;
|
|
73
|
+
let consensusNonSuperNodes = 0;
|
|
74
|
+
let archiveSources = 0;
|
|
75
|
+
let blobSinks = 0;
|
|
73
76
|
if (l1ConsensusHostUrls && l1ConsensusHostUrls.length > 0) {
|
|
74
77
|
for(let l1ConsensusHostIndex = 0; l1ConsensusHostIndex < l1ConsensusHostUrls.length; l1ConsensusHostIndex++){
|
|
75
78
|
const l1ConsensusHostUrl = l1ConsensusHostUrls[l1ConsensusHostIndex];
|
|
76
79
|
try {
|
|
77
|
-
const { url, ...options } = getBeaconNodeFetchOptions(`${l1ConsensusHostUrl}/eth/v1/beacon/headers`, this.config, l1ConsensusHostIndex);
|
|
80
|
+
const { url, ...options } = getBeaconNodeFetchOptions(`${l1ConsensusHostUrl}/eth/v1/beacon/headers/head`, this.config, l1ConsensusHostIndex);
|
|
78
81
|
const res = await this.fetch(url, options);
|
|
79
|
-
if (res.ok) {
|
|
80
|
-
this.log.
|
|
82
|
+
if (!res.ok) {
|
|
83
|
+
this.log.error(`Failure reaching L1 consensus host: ${res.statusText} (${res.status})`, {
|
|
81
84
|
l1ConsensusHostUrl
|
|
82
85
|
});
|
|
83
|
-
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
this.log.info(`L1 consensus host is reachable`, {
|
|
89
|
+
l1ConsensusHostUrl
|
|
90
|
+
});
|
|
91
|
+
// Check if the host serves blob sidecars (supernode/semi-supernode).
|
|
92
|
+
// Post-Fusaka (PeerDAS), non-supernode beacon nodes no longer serve the
|
|
93
|
+
// blob sidecar endpoint. A 200 response (even with an empty data array
|
|
94
|
+
// for a slot with no blobs) means the node supports serving blob sidecars.
|
|
95
|
+
const body = await res.json();
|
|
96
|
+
const headSlot = body?.data?.header?.message?.slot;
|
|
97
|
+
if (headSlot) {
|
|
98
|
+
const { url: blobUrl, ...blobOptions } = getBeaconNodeFetchOptions(`${l1ConsensusHostUrl}/eth/v1/beacon/blobs/${headSlot}`, this.config, l1ConsensusHostIndex);
|
|
99
|
+
const blobRes = await this.fetch(blobUrl, blobOptions);
|
|
100
|
+
if (blobRes.ok) {
|
|
101
|
+
this.log.info(`L1 consensus host serves blob sidecars (supernode)`, {
|
|
102
|
+
l1ConsensusHostUrl
|
|
103
|
+
});
|
|
104
|
+
consensusSuperNodes++;
|
|
105
|
+
} else {
|
|
106
|
+
this.log.info(`L1 consensus host does not serve blob sidecars`, {
|
|
107
|
+
l1ConsensusHostUrl
|
|
108
|
+
});
|
|
109
|
+
consensusNonSuperNodes++;
|
|
110
|
+
}
|
|
84
111
|
} else {
|
|
85
|
-
this.log.
|
|
112
|
+
this.log.info(`L1 consensus host is reachable but could not determine head slot`, {
|
|
86
113
|
l1ConsensusHostUrl
|
|
87
114
|
});
|
|
115
|
+
consensusNonSuperNodes++;
|
|
88
116
|
}
|
|
89
117
|
} catch (err) {
|
|
90
118
|
this.log.error(`Error reaching L1 consensus host`, err, {
|
|
@@ -92,8 +120,6 @@ export class HttpBlobClient {
|
|
|
92
120
|
});
|
|
93
121
|
}
|
|
94
122
|
}
|
|
95
|
-
} else {
|
|
96
|
-
this.log.warn('No L1 consensus host urls configured');
|
|
97
123
|
}
|
|
98
124
|
if (this.archiveClient) {
|
|
99
125
|
try {
|
|
@@ -102,14 +128,12 @@ export class HttpBlobClient {
|
|
|
102
128
|
latest,
|
|
103
129
|
archiveUrl
|
|
104
130
|
});
|
|
105
|
-
|
|
131
|
+
archiveSources++;
|
|
106
132
|
} catch (err) {
|
|
107
133
|
this.log.error(`Error reaching archive client`, err, {
|
|
108
134
|
archiveUrl
|
|
109
135
|
});
|
|
110
136
|
}
|
|
111
|
-
} else {
|
|
112
|
-
this.log.warn('No archive client configured');
|
|
113
137
|
}
|
|
114
138
|
if (this.fileStoreClients.length > 0) {
|
|
115
139
|
for (const fileStoreClient of this.fileStoreClients){
|
|
@@ -119,7 +143,7 @@ export class HttpBlobClient {
|
|
|
119
143
|
this.log.info(`FileStore is reachable`, {
|
|
120
144
|
url: fileStoreClient.getBaseUrl()
|
|
121
145
|
});
|
|
122
|
-
|
|
146
|
+
blobSinks++;
|
|
123
147
|
} else {
|
|
124
148
|
this.log.warn(`FileStore is not accessible`, {
|
|
125
149
|
url: fileStoreClient.getBaseUrl()
|
|
@@ -132,12 +156,22 @@ export class HttpBlobClient {
|
|
|
132
156
|
}
|
|
133
157
|
}
|
|
134
158
|
}
|
|
159
|
+
// Emit a single summary after validating all sources
|
|
160
|
+
const successfulSourceCount = consensusSuperNodes + archiveSources + blobSinks;
|
|
161
|
+
let summary = `Blob client running with consensusSuperNodes=${consensusSuperNodes} archiveSources=${archiveSources} blobSinks=${blobSinks}`;
|
|
162
|
+
if (consensusNonSuperNodes > 0) {
|
|
163
|
+
summary += `. ${consensusNonSuperNodes} consensus client(s) ignored because they are not running in supernode or semi-supernode mode`;
|
|
164
|
+
}
|
|
135
165
|
if (successfulSourceCount === 0) {
|
|
136
166
|
if (this.config.blobAllowEmptySources) {
|
|
137
|
-
this.log.warn(
|
|
167
|
+
this.log.warn(summary);
|
|
138
168
|
} else {
|
|
139
|
-
throw new Error(
|
|
169
|
+
throw new Error(summary);
|
|
140
170
|
}
|
|
171
|
+
} else if (consensusSuperNodes === 0) {
|
|
172
|
+
this.log.warn(summary);
|
|
173
|
+
} else {
|
|
174
|
+
this.log.info(summary);
|
|
141
175
|
}
|
|
142
176
|
}
|
|
143
177
|
async sendBlobsToFilestore(blobs) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aztec/blob-client",
|
|
3
|
-
"version": "0.0.1-commit.
|
|
3
|
+
"version": "0.0.1-commit.ce4f8c4f2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": "./dest/client/bin/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -56,12 +56,12 @@
|
|
|
56
56
|
]
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
|
-
"@aztec/blob-lib": "0.0.1-commit.
|
|
60
|
-
"@aztec/ethereum": "0.0.1-commit.
|
|
61
|
-
"@aztec/foundation": "0.0.1-commit.
|
|
62
|
-
"@aztec/kv-store": "0.0.1-commit.
|
|
63
|
-
"@aztec/stdlib": "0.0.1-commit.
|
|
64
|
-
"@aztec/telemetry-client": "0.0.1-commit.
|
|
59
|
+
"@aztec/blob-lib": "0.0.1-commit.ce4f8c4f2",
|
|
60
|
+
"@aztec/ethereum": "0.0.1-commit.ce4f8c4f2",
|
|
61
|
+
"@aztec/foundation": "0.0.1-commit.ce4f8c4f2",
|
|
62
|
+
"@aztec/kv-store": "0.0.1-commit.ce4f8c4f2",
|
|
63
|
+
"@aztec/stdlib": "0.0.1-commit.ce4f8c4f2",
|
|
64
|
+
"@aztec/telemetry-client": "0.0.1-commit.ce4f8c4f2",
|
|
65
65
|
"express": "^4.21.2",
|
|
66
66
|
"snappy": "^7.2.2",
|
|
67
67
|
"source-map-support": "^0.5.21",
|
package/src/client/http.ts
CHANGED
|
@@ -95,44 +95,68 @@ export class HttpBlobClient implements BlobClientInterface {
|
|
|
95
95
|
const archiveUrl = this.archiveClient?.getBaseUrl();
|
|
96
96
|
this.log.info(`Testing configured blob sources`, { l1ConsensusHostUrls, archiveUrl });
|
|
97
97
|
|
|
98
|
-
let
|
|
98
|
+
let consensusSuperNodes = 0;
|
|
99
|
+
let consensusNonSuperNodes = 0;
|
|
100
|
+
let archiveSources = 0;
|
|
101
|
+
let blobSinks = 0;
|
|
99
102
|
|
|
100
103
|
if (l1ConsensusHostUrls && l1ConsensusHostUrls.length > 0) {
|
|
101
104
|
for (let l1ConsensusHostIndex = 0; l1ConsensusHostIndex < l1ConsensusHostUrls.length; l1ConsensusHostIndex++) {
|
|
102
105
|
const l1ConsensusHostUrl = l1ConsensusHostUrls[l1ConsensusHostIndex];
|
|
103
106
|
try {
|
|
104
107
|
const { url, ...options } = getBeaconNodeFetchOptions(
|
|
105
|
-
`${l1ConsensusHostUrl}/eth/v1/beacon/headers`,
|
|
108
|
+
`${l1ConsensusHostUrl}/eth/v1/beacon/headers/head`,
|
|
106
109
|
this.config,
|
|
107
110
|
l1ConsensusHostIndex,
|
|
108
111
|
);
|
|
109
112
|
const res = await this.fetch(url, options);
|
|
110
|
-
if (res.ok) {
|
|
111
|
-
this.log.info(`L1 consensus host is reachable`, { l1ConsensusHostUrl });
|
|
112
|
-
successfulSourceCount++;
|
|
113
|
-
} else {
|
|
113
|
+
if (!res.ok) {
|
|
114
114
|
this.log.error(`Failure reaching L1 consensus host: ${res.statusText} (${res.status})`, {
|
|
115
115
|
l1ConsensusHostUrl,
|
|
116
116
|
});
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
this.log.info(`L1 consensus host is reachable`, { l1ConsensusHostUrl });
|
|
121
|
+
|
|
122
|
+
// Check if the host serves blob sidecars (supernode/semi-supernode).
|
|
123
|
+
// Post-Fusaka (PeerDAS), non-supernode beacon nodes no longer serve the
|
|
124
|
+
// blob sidecar endpoint. A 200 response (even with an empty data array
|
|
125
|
+
// for a slot with no blobs) means the node supports serving blob sidecars.
|
|
126
|
+
const body = await res.json();
|
|
127
|
+
const headSlot = body?.data?.header?.message?.slot;
|
|
128
|
+
if (headSlot) {
|
|
129
|
+
const { url: blobUrl, ...blobOptions } = getBeaconNodeFetchOptions(
|
|
130
|
+
`${l1ConsensusHostUrl}/eth/v1/beacon/blobs/${headSlot}`,
|
|
131
|
+
this.config,
|
|
132
|
+
l1ConsensusHostIndex,
|
|
133
|
+
);
|
|
134
|
+
const blobRes = await this.fetch(blobUrl, blobOptions);
|
|
135
|
+
if (blobRes.ok) {
|
|
136
|
+
this.log.info(`L1 consensus host serves blob sidecars (supernode)`, { l1ConsensusHostUrl });
|
|
137
|
+
consensusSuperNodes++;
|
|
138
|
+
} else {
|
|
139
|
+
this.log.info(`L1 consensus host does not serve blob sidecars`, { l1ConsensusHostUrl });
|
|
140
|
+
consensusNonSuperNodes++;
|
|
141
|
+
}
|
|
142
|
+
} else {
|
|
143
|
+
this.log.info(`L1 consensus host is reachable but could not determine head slot`, { l1ConsensusHostUrl });
|
|
144
|
+
consensusNonSuperNodes++;
|
|
117
145
|
}
|
|
118
146
|
} catch (err) {
|
|
119
147
|
this.log.error(`Error reaching L1 consensus host`, err, { l1ConsensusHostUrl });
|
|
120
148
|
}
|
|
121
149
|
}
|
|
122
|
-
} else {
|
|
123
|
-
this.log.warn('No L1 consensus host urls configured');
|
|
124
150
|
}
|
|
125
151
|
|
|
126
152
|
if (this.archiveClient) {
|
|
127
153
|
try {
|
|
128
154
|
const latest = await this.archiveClient.getLatestBlock();
|
|
129
155
|
this.log.info(`Archive client is reachable and synced to L1 block ${latest.number}`, { latest, archiveUrl });
|
|
130
|
-
|
|
156
|
+
archiveSources++;
|
|
131
157
|
} catch (err) {
|
|
132
158
|
this.log.error(`Error reaching archive client`, err, { archiveUrl });
|
|
133
159
|
}
|
|
134
|
-
} else {
|
|
135
|
-
this.log.warn('No archive client configured');
|
|
136
160
|
}
|
|
137
161
|
|
|
138
162
|
if (this.fileStoreClients.length > 0) {
|
|
@@ -141,7 +165,7 @@ export class HttpBlobClient implements BlobClientInterface {
|
|
|
141
165
|
const accessible = await fileStoreClient.testConnection();
|
|
142
166
|
if (accessible) {
|
|
143
167
|
this.log.info(`FileStore is reachable`, { url: fileStoreClient.getBaseUrl() });
|
|
144
|
-
|
|
168
|
+
blobSinks++;
|
|
145
169
|
} else {
|
|
146
170
|
this.log.warn(`FileStore is not accessible`, { url: fileStoreClient.getBaseUrl() });
|
|
147
171
|
}
|
|
@@ -151,12 +175,24 @@ export class HttpBlobClient implements BlobClientInterface {
|
|
|
151
175
|
}
|
|
152
176
|
}
|
|
153
177
|
|
|
178
|
+
// Emit a single summary after validating all sources
|
|
179
|
+
const successfulSourceCount = consensusSuperNodes + archiveSources + blobSinks;
|
|
180
|
+
|
|
181
|
+
let summary = `Blob client running with consensusSuperNodes=${consensusSuperNodes} archiveSources=${archiveSources} blobSinks=${blobSinks}`;
|
|
182
|
+
if (consensusNonSuperNodes > 0) {
|
|
183
|
+
summary += `. ${consensusNonSuperNodes} consensus client(s) ignored because they are not running in supernode or semi-supernode mode`;
|
|
184
|
+
}
|
|
185
|
+
|
|
154
186
|
if (successfulSourceCount === 0) {
|
|
155
187
|
if (this.config.blobAllowEmptySources) {
|
|
156
|
-
this.log.warn(
|
|
188
|
+
this.log.warn(summary);
|
|
157
189
|
} else {
|
|
158
|
-
throw new Error(
|
|
190
|
+
throw new Error(summary);
|
|
159
191
|
}
|
|
192
|
+
} else if (consensusSuperNodes === 0) {
|
|
193
|
+
this.log.warn(summary);
|
|
194
|
+
} else {
|
|
195
|
+
this.log.info(summary);
|
|
160
196
|
}
|
|
161
197
|
}
|
|
162
198
|
|