-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
move rewards update loop out of zinnia loop (#462)
* move rewards update loop out of zinnia loop * fix: initialise `lastRewardsScheduledForAddress` Signed-off-by: Miroslav Bajtoš <oss@bajtos.net> * fix: print full details for event handler errors Signed-off-by: Miroslav Bajtoš <oss@bajtos.net> --------- Signed-off-by: Miroslav Bajtoš <oss@bajtos.net> Co-authored-by: Miroslav Bajtoš <oss@bajtos.net>
- Loading branch information
1 parent
9d112af
commit bdb853f
Showing
5 changed files
with
165 additions
and
130 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import timers from 'node:timers/promises' | ||
import pRetry from 'p-retry' | ||
import * as Name from 'w3name' | ||
import { ethers } from 'ethers' | ||
|
||
const { | ||
// https://github.com/filecoin-station/contract-addresses | ||
CONTRACT_ADDRESSES_IPNS_KEY = 'k51qzi5uqu5dmaqrefqazad0ca8b24fb79zlacfjw2awdt5gjf2cr6jto5jyqe' | ||
} = process.env | ||
|
||
export const runUpdateContractsLoop = async ({ provider, abi, contracts }) => { | ||
while (true) { | ||
const delay = 10 * 60 * 1000 // 10 minutes | ||
const jitter = Math.random() * 20_000 - 10_000 // +- 10 seconds | ||
try { | ||
await timers.setTimeout(delay + jitter) | ||
} catch (err) { | ||
if (err.name === 'AbortError') return | ||
throw err | ||
} | ||
contracts.set(await getContractsWithRetry({ provider, abi })) | ||
} | ||
} | ||
|
||
async function getContractsWithRetry ({ provider, abi }) { | ||
const contractAddresses = await pRetry(getContractAddresses, { | ||
retries: 10, | ||
onFailedAttempt: err => { | ||
console.error(err) | ||
console.error('Failed to get contract addresses. Retrying...') | ||
if (String(err).includes('You are being rate limited')) { | ||
const delaySeconds = 60 + (Math.random() * 60) | ||
// Don't DDOS the w3name services | ||
console.error( | ||
`Rate limited. Waiting ${delaySeconds} seconds...` | ||
) | ||
return timers.setTimeout(delaySeconds * 1000) | ||
} | ||
} | ||
}) | ||
console.error(`Meridian contract addresses: ${contractAddresses.join(', ')}`) | ||
return contractAddresses.map(address => { | ||
return new ethers.Contract(address, abi, provider) | ||
}) | ||
} | ||
|
||
async function getContractAddresses () { | ||
const name = Name.parse(CONTRACT_ADDRESSES_IPNS_KEY) | ||
const revision = await Name.resolve(name) | ||
return revision.value.split('\n').filter(Boolean) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
export class Obj { | ||
constructor (value = null) { | ||
this._value = value | ||
} | ||
|
||
set (val) { | ||
this._value = val | ||
} | ||
|
||
get () { | ||
return this._value | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import timers from 'node:timers/promises' | ||
|
||
export const runUpdateRewardsLoop = async ({ contracts, ethAddress, onMetrics, lastTotalJobsCompleted, lastRewardsScheduledForAddress }) => { | ||
while (true) { | ||
while (!contracts.get()) { | ||
await timers.setTimeout(1000) | ||
} | ||
const contractRewards = await Promise.all(contracts.get().map(async contract => { | ||
return getScheduledRewardsWithFallback(contract, ethAddress) | ||
})) | ||
const totalRewards = contractRewards.reduce((a, b) => a + b, 0n) | ||
onMetrics({ | ||
totalJobsCompleted: lastTotalJobsCompleted.get(), | ||
rewardsScheduledForAddress: totalRewards | ||
}) | ||
lastRewardsScheduledForAddress.set(totalRewards) | ||
|
||
const delay = 10 * 60 * 1000 // 10 minutes | ||
const jitter = Math.random() * 20_000 - 10_000 // +- 10 seconds | ||
await timers.setTimeout(delay + jitter) | ||
} | ||
} | ||
|
||
async function getScheduledRewardsWithFallback (contract, ethAddress) { | ||
try { | ||
return await contract.rewardsScheduledFor(ethAddress) | ||
} catch (err) { | ||
console.error('Failed to get scheduled rewards:', err.stack) | ||
return 0n | ||
} | ||
} |
Oops, something went wrong.