-
Notifications
You must be signed in to change notification settings - Fork 226
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
missing oracles cause promise growth #9923
Comments
Ok so vaultManager.js has this function named observeQuoteNotifier() {
const { state } = this;
const { collateralBrand, collateralUnit, debtBrand, storageNode } =
state;
const ephemera = collateralEphemera(collateralBrand);
const quoteNotifier = E(priceAuthority).makeQuoteNotifier(
collateralUnit,
debtBrand,
);
// @ts-expect-error XXX quotes
ephemera.storedQuotesNotifier = makeStoredNotifier(
// @ts-expect-error XXX quotes
quoteNotifier,
E(storageNode).makeChildNode('quotes'),
marshaller,
);
trace(
'helper.start() awaiting observe storedQuotesNotifier',
collateralBrand,
);
// NB: upon restart, there may not be a price for a while. If manager
// operations are permitted, ones that depend on price information
// will throw. See https://github.com/Agoric/agoric-sdk/issues/4317
const quoteWatcher = harden({
onFulfilled(value) {
ephemera.storedCollateralQuote = value;
},
onRejected() {
// NOTE: drastic action, if the quoteNotifier fails, we don't know
// the value of the asset, nor do we know how long we'll be in
// ignorance. Best choice is to disable actions that require
// prices and restart when we have a new price. If we restart the
// notifier immediately, we'll trigger an infinite loop, so try
// to restart each time we get a request.
ephemera.storedCollateralQuote = null;
},
});
void watchQuoteNotifier(quoteNotifier, quoteWatcher);
}, The goal is to populate This function is called from several places in vaultManager that need a stored quote, with a clause like: if (!storedCollateralQuote) {
facets.helper.observeQuoteNotifier();
throw Fail`maxDebtFor called before a collateral quote was available for ${collateralBrand}`;
} and at least one of those places can be triggered by an hourly timer wakeup. Which means every timer wakeup will provoke this new set of objects and promises, until some QuoteNotifier finally reports either a price or an error. And something deeper in the process is unable to do either without a PushPrice coming in from off-chain, which isn't happening on the testnet. shape of a fixI think we need that We want Maybe something that starts with: if (!ephemera.quoteNotifier) {
ephemera.quoteNotifier = E(priceAuthority).makeQuoteNotifier();
ephemera.quoteNotifier.catch(_err => ephemera.quoteNotifier = undefined);
} It should probably defer building the rest of the wrapping objects until we get a quote notifier back. The goal is to not ever build redundant objects, or make redundant requests. relation to promise growthNote that I still don't know exactly which promise is the one being accumulated. I know it's one of the |
Resolved by #10668 |
In https://github.com/Agoric/agoric-private/issues/169 we observed constant growth in the number of unresolved promises, in a testnet that was mainfork-cloned from our mainnet, but which lacked its own oracles, and thus was not supplied with price quotes. My analysis notes from that ticket:
We don't expect to be in this situation on a real network, at least not for very long. Oracles will do their job, prices will flow, auctions will happen. But:
The task is to understand exactly where these promises are coming from, what action whose lack is causing them to be generated, and then fix the code to prevent the long-term growth.
The text was updated successfully, but these errors were encountered: