@agoric/client-utils 0.1.1-dev-c236c55.0 → 0.1.1-dev-d19b293.0

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.
Files changed (2) hide show
  1. package/package.json +7 -7
  2. package/src/sync-tools.js +50 -20
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/client-utils",
3
- "version": "0.1.1-dev-c236c55.0+c236c55",
3
+ "version": "0.1.1-dev-d19b293.0+d19b293",
4
4
  "description": "Utilities for building Agoric clients",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {
@@ -27,11 +27,11 @@
27
27
  "ts-blank-space": "^0.4.1"
28
28
  },
29
29
  "dependencies": {
30
- "@agoric/casting": "0.4.3-dev-c236c55.0+c236c55",
31
- "@agoric/ertp": "0.16.3-dev-c236c55.0+c236c55",
32
- "@agoric/internal": "0.3.3-dev-c236c55.0+c236c55",
33
- "@agoric/smart-wallet": "0.5.4-dev-c236c55.0+c236c55",
34
- "@agoric/vats": "0.15.2-dev-c236c55.0+c236c55",
30
+ "@agoric/casting": "0.4.3-dev-d19b293.0+d19b293",
31
+ "@agoric/ertp": "0.16.3-dev-d19b293.0+d19b293",
32
+ "@agoric/internal": "0.3.3-dev-d19b293.0+d19b293",
33
+ "@agoric/smart-wallet": "0.5.4-dev-d19b293.0+d19b293",
34
+ "@agoric/vats": "0.15.2-dev-d19b293.0+d19b293",
35
35
  "@cosmjs/stargate": "^0.32.3",
36
36
  "@cosmjs/tendermint-rpc": "^0.32.3",
37
37
  "@endo/common": "^1.2.7",
@@ -58,5 +58,5 @@
58
58
  ],
59
59
  "timeout": "20m"
60
60
  },
61
- "gitHead": "c236c55c008a83a28d324026dcc4a8411a0c4f05"
61
+ "gitHead": "d19b293d5b28a2d78754eb7912771bdb66d5fb37"
62
62
  }
package/src/sync-tools.js CHANGED
@@ -16,6 +16,7 @@
16
16
  * @typedef {object} RetryOptions
17
17
  * @property {number} [maxRetries]
18
18
  * @property {number} [retryIntervalMs]
19
+ * @property {boolean} [reusePromise]
19
20
  *
20
21
  * @typedef {RetryOptions & {errorMessage: string}} WaitUntilOptions
21
22
  *
@@ -48,19 +49,51 @@ export const retryUntilCondition = async (
48
49
  operation,
49
50
  condition,
50
51
  message,
51
- { maxRetries = 6, retryIntervalMs = 3500, log = console.log, setTimeout },
52
+ {
53
+ maxRetries = 6,
54
+ retryIntervalMs = 3500,
55
+ reusePromise = false,
56
+ // XXX mixes ocaps with configuration options
57
+ log = console.log,
58
+ setTimeout,
59
+ },
52
60
  ) => {
53
- console.log({ maxRetries, retryIntervalMs, message });
54
- let retries = 0;
61
+ console.log({ maxRetries, retryIntervalMs, reusePromise, message });
55
62
 
56
63
  await null; // separate sync prologue
57
64
 
65
+ const timedOut = Symbol('timed out');
66
+ let retries = 0;
67
+ /** @type {Promise | undefined } */
68
+ let resultP;
58
69
  while (retries < maxRetries) {
59
70
  try {
60
- const result = await operation();
61
- log('RESULT', result);
62
- if (condition(result)) {
63
- return result;
71
+ if (!reusePromise || !resultP) {
72
+ resultP = operation();
73
+ const makeCleanup = ref => {
74
+ const cleanup = () => {
75
+ if (resultP === ref) {
76
+ resultP = undefined;
77
+ }
78
+ };
79
+ return cleanup;
80
+ };
81
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
82
+ resultP.finally(makeCleanup(resultP));
83
+ }
84
+ const result = await Promise.race([
85
+ resultP,
86
+ // Overload the retryIntervalMs to apply both *to* and *between* iterations
87
+ sleep(retryIntervalMs, { log() {}, setTimeout }).then(() => timedOut),
88
+ ]);
89
+ if (result === timedOut) {
90
+ log(`Attempt ${retries + 1} timed out`);
91
+ if (!reusePromise) resultP = undefined;
92
+ } else {
93
+ log('RESULT', result);
94
+ if (condition(result)) {
95
+ return result;
96
+ }
64
97
  }
65
98
  } catch (error) {
66
99
  if (error instanceof Error) {
@@ -82,13 +115,14 @@ export const retryUntilCondition = async (
82
115
 
83
116
  /**
84
117
  * @param {WaitUntilOptions} options
118
+ * @returns {WaitUntilOptions & {log?: typeof console.log}}
85
119
  */
86
120
  const overrideDefaultOptions = options => {
87
121
  const defaultValues = {
88
122
  maxRetries: 6,
89
123
  retryIntervalMs: 3500,
90
- log: console.log,
91
124
  errorMessage: 'Error',
125
+ log: console.log,
92
126
  };
93
127
 
94
128
  return { ...defaultValues, ...options };
@@ -118,14 +152,13 @@ export const waitUntilContractDeployed = (
118
152
  ) => {
119
153
  const { follow, setTimeout } = ambientAuthority;
120
154
  const getInstances = makeGetInstances(follow);
121
- const { maxRetries, retryIntervalMs, errorMessage, log } =
122
- overrideDefaultOptions(options);
155
+ const { errorMessage, ...resolvedOptions } = overrideDefaultOptions(options);
123
156
 
124
157
  return retryUntilCondition(
125
158
  getInstances,
126
159
  instanceObject => Object.keys(instanceObject).includes(contractName),
127
160
  errorMessage,
128
- { maxRetries, retryIntervalMs, log, setTimeout },
161
+ { setTimeout, ...resolvedOptions },
129
162
  );
130
163
  };
131
164
 
@@ -156,14 +189,13 @@ const checkCosmosBalance = (balances, threshold) => {
156
189
  export const waitUntilAccountFunded = (destAcct, io, threshold, options) => {
157
190
  const { query, setTimeout } = io;
158
191
  const queryCosmosBalance = makeQueryCosmosBalance(query);
159
- const { maxRetries, retryIntervalMs, errorMessage, log } =
160
- overrideDefaultOptions(options);
192
+ const { errorMessage, ...resolvedOptions } = overrideDefaultOptions(options);
161
193
 
162
194
  return retryUntilCondition(
163
195
  async () => queryCosmosBalance(destAcct),
164
196
  balances => checkCosmosBalance(balances, threshold),
165
197
  errorMessage,
166
- { maxRetries, retryIntervalMs, log, setTimeout },
198
+ { setTimeout, ...resolvedOptions },
167
199
  );
168
200
  };
169
201
 
@@ -211,14 +243,13 @@ export const waitUntilOfferResult = (
211
243
  ) => {
212
244
  const { follow, setTimeout } = io;
213
245
  const queryWallet = makeQueryWallet(follow);
214
- const { maxRetries, retryIntervalMs, errorMessage, log } =
215
- overrideDefaultOptions(options);
246
+ const { errorMessage, ...resolvedOptions } = overrideDefaultOptions(options);
216
247
 
217
248
  return retryUntilCondition(
218
249
  async () => queryWallet(addr),
219
250
  status => checkOfferState(status, waitForPayouts, offerId),
220
251
  errorMessage,
221
- { maxRetries, retryIntervalMs, log, setTimeout },
252
+ { reusePromise: true, setTimeout, ...resolvedOptions },
222
253
  );
223
254
  };
224
255
 
@@ -247,13 +278,12 @@ const checkForInvitation = update => {
247
278
  export const waitUntilInvitationReceived = (addr, io, options) => {
248
279
  const { follow, setTimeout } = io;
249
280
  const queryWallet = makeQueryWallet(follow);
250
- const { maxRetries, retryIntervalMs, errorMessage, log } =
251
- overrideDefaultOptions(options);
281
+ const { errorMessage, ...resolvedOptions } = overrideDefaultOptions(options);
252
282
 
253
283
  return retryUntilCondition(
254
284
  async () => queryWallet(addr),
255
285
  checkForInvitation,
256
286
  errorMessage,
257
- { maxRetries, retryIntervalMs, log, setTimeout },
287
+ { reusePromise: true, setTimeout, ...resolvedOptions },
258
288
  );
259
289
  };