Skip to content

Commit a8344b0

Browse files
committed
fix: data sync + enable observability
1 parent df5fa8c commit a8344b0

File tree

6 files changed

+26
-29
lines changed

6 files changed

+26
-29
lines changed

packages/nimiq-validator-trustscore/src/fetcher.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,19 @@ export interface FetchActivityOptions extends Pick<BaseAlbatrossPolicyOptions, '
1111
* @default 5
1212
*/
1313
maxRetries?: number
14+
/**
15+
* Max concurrent RPC requests per batch. Workers allows ~6 concurrent outbound connections.
16+
* @default 120
17+
*/
18+
maxBatchSize?: number
1419
}
1520

1621
/**
1722
* For a given block number, fetches the validator slots assignation.
1823
* The block number MUST be an election block otherwise it will return an error result.
1924
*/
2025
export async function fetchActivity(epochIndex: number, options: FetchActivityOptions = {}): Result<EpochActivity> {
21-
const { maxRetries = 5, network = 'mainnet' } = options
26+
const { maxRetries = 5, network = 'mainnet', maxBatchSize: _maxBatchSize = 120 } = options
2227
// Epochs start at 1, but election block is the first block of the epoch
2328
const electionBlock = electionBlockOf(epochIndex, { network })!
2429
const [isBlockOk, errorBlockNumber, block] = await getBlockByNumber({ blockNumber: electionBlock, includeBody: false })
@@ -51,8 +56,8 @@ export async function fetchActivity(epochIndex: number, options: FetchActivityOp
5156
epochActivity[validator] = { address: validator, likelihood, missed: 0, rewarded: 0, dominanceRatioViaBalance, dominanceRatioViaSlots, balance, elected: true, stakers: 0 } as ElectedValidator
5257
}
5358

54-
const maxBatchSize = 120
55-
const minBatchSize = 10
59+
const maxBatchSize = _maxBatchSize
60+
const minBatchSize = Math.min(10, maxBatchSize)
5661
let batchSize = maxBatchSize
5762

5863
const createPromise = async (index: number, retryCount = 0): Promise<ResultSync<void>> => {

server/assets/validators

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../public/validators

server/tasks/cron/sync.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,10 @@ export default defineTask({
5252
for (const taskName of TASKS) {
5353
consola.info(`[cron:sync] running ${taskName}`)
5454
const res = await runTask(taskName, { payload: event.payload ?? {}, context: event.context ?? {} })
55-
results[taskName] = (res as any)?.result ?? res
55+
const result = (res as any)?.result ?? res
56+
results[taskName] = result
57+
if (result?.success === false)
58+
throw new Error(`${taskName} failed: ${result.error || 'unknown'}`)
5659
}
5760

5861
if (cronRunId) {

server/tasks/sync/epochs.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export default defineTask({
3939
break
4040

4141
const missingEpoch = missingEpochs.at(0)!
42-
const [activityOk, activityError, epochActivity] = await fetchActivity(missingEpoch)
42+
const [activityOk, activityError, epochActivity] = await fetchActivity(missingEpoch, { network: config.public.nimiqNetwork, maxBatchSize: import.meta.dev ? 120 : 6 })
4343
if (!activityOk || !epochActivity) {
4444
const error = new Error(activityError || 'Unable to fetch activity')
4545
await sendSyncFailureNotification('missing-epoch', error)

server/utils/validators-bundle.ts

Lines changed: 8 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -7,46 +7,31 @@ interface ImportValidatorsBundledOptions {
77
shouldStore?: boolean
88
}
99

10-
function normalizePath(value: string) {
11-
return value.replace(/\\/g, '/')
12-
}
13-
14-
function extractNetworkFromPath(path: string) {
15-
const normalized = normalizePath(path)
16-
const match = normalized.match(/(?:^|\/)public\/validators\/([^/]+)\/[^/]+\.json$/)
17-
return match?.[1]
18-
}
19-
2010
export async function importValidatorsBundled(nimiqNetwork?: string, options: ImportValidatorsBundledOptions = {}): Result<ValidatorJSON[]> {
2111
if (!nimiqNetwork)
2212
return [false, 'Nimiq network is required', undefined]
2313

2414
const { shouldStore = true } = options
25-
const modules = import.meta.glob('../../public/validators/*/*.json', { eager: true, import: 'default' })
15+
const storage = useStorage('assets:server:validators')
16+
const keys = await storage.getKeys(`${nimiqNetwork}`)
2617

2718
const validators: ValidatorJSON[] = []
28-
for (const [path, mod] of Object.entries(modules)) {
29-
if (path.endsWith('.example.json'))
19+
for (const key of keys) {
20+
if (!key.endsWith('.json') || key.endsWith('.example.json'))
3021
continue
3122

32-
const network = extractNetworkFromPath(path)
33-
if (!network || network !== nimiqNetwork)
34-
continue
35-
36-
const data = (mod as any)?.default ?? mod
23+
const data = await storage.getItem(key)
3724
const parsed = validatorSchema.safeParse(data)
38-
if (!parsed.success) {
39-
return [false, `Invalid validator data at ${path}: ${parsed.error}`, undefined]
40-
}
25+
if (!parsed.success)
26+
return [false, `Invalid validator data at ${key}: ${parsed.error}`, undefined]
4127
validators.push(parsed.data)
4228
}
4329

4430
if (!shouldStore)
4531
return [true, undefined, validators]
4632

47-
if (validators.length === 0) {
33+
if (validators.length === 0)
4834
return [false, `No bundled validators found for network: ${nimiqNetwork}`, undefined]
49-
}
5035

5136
const results = await Promise.allSettled(validators.map(v => storeValidator(v.address, v, { upsert: true })))
5237
const failures = results.filter(r => r.status === 'rejected')

wrangler.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"observability": {
1010
"enabled": true,
1111
"logs": {
12-
"enabled": false,
12+
"enabled": true,
1313
"invocation_logs": true
1414
}
1515
},
@@ -24,6 +24,7 @@
2424
"main": "dist/server/index.mjs",
2525
"assets": { "directory": "dist/public" },
2626
"compatibility_flags": ["nodejs_compat"],
27+
"observability": { "enabled": true, "logs": { "enabled": true, "invocation_logs": true } },
2728
"triggers": { "crons": ["0 */12 * * *"] },
2829
"vars": { "NUXT_PUBLIC_NIMIQ_NETWORK": "main-albatross" },
2930
"d1_databases": [{ "binding": "DB", "database_id": "dd9fa8b7-f5a1-48ab-b0af-d93d1092b89a", "database_name": "validators-api-mainnet-preview" }],
@@ -35,6 +36,7 @@
3536
"main": "dist/server/index.mjs",
3637
"assets": { "directory": "dist/public" },
3738
"compatibility_flags": ["nodejs_compat"],
39+
"observability": { "enabled": true, "logs": { "enabled": true, "invocation_logs": true } },
3840
"triggers": { "crons": ["0 */12 * * *"] },
3941
"vars": { "NUXT_PUBLIC_NIMIQ_NETWORK": "test-albatross" },
4042
"d1_databases": [{ "binding": "DB", "database_id": "de14e353-5028-4e52-a383-a9cc200d960d", "database_name": "validators-api-testnet" }],
@@ -46,6 +48,7 @@
4648
"main": "dist/server/index.mjs",
4749
"assets": { "directory": "dist/public" },
4850
"compatibility_flags": ["nodejs_compat"],
51+
"observability": { "enabled": true, "logs": { "enabled": true, "invocation_logs": true } },
4952
"triggers": { "crons": ["0 */12 * * *"] },
5053
"vars": { "NUXT_PUBLIC_NIMIQ_NETWORK": "test-albatross" },
5154
"d1_databases": [{ "binding": "DB", "database_id": "da6931b2-6d06-4598-911b-fba1fa19efd2", "database_name": "validators-api-testnet-preview" }],

0 commit comments

Comments
 (0)