Skip to content

Commit

Permalink
feat(lint): exempt connectionHandler notification methods from resuma…
Browse files Browse the repository at this point in the history
…ble rule

- onOpen and onClose are event listeners that handle incoming notifications
- these methods do not return values and are not expected to be resumable
  • Loading branch information
0xpatrickdev committed Jun 25, 2024
1 parent 465b415 commit f409a8d
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 26 deletions.
4 changes: 3 additions & 1 deletion .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ const deprecatedTerminology = Object.fromEntries(
*/
const resumable = [
{
selector: 'FunctionExpression[async=true]',
// all async function expressions, except `onOpen` and `onClose` when they are properties of `connectionHandler`
selector:
'FunctionExpression[async=true]:not(Property[key.name="connectionHandler"] > ObjectExpression > Property[key.name=/^(onOpen|onClose)$/] > FunctionExpression[async=true])',
message: 'Non-immediate functions must return vows, not promises',
},
{
Expand Down
28 changes: 8 additions & 20 deletions packages/orchestration/src/exos/chain-account-kit.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { makeTxPacket, parseTxPacket } from '../utils/packet.js';
/**
* @import {Zone} from '@agoric/base-zone';
* @import {Connection, Port} from '@agoric/network';
* @import {PromiseVow, Remote, Vow, VowTools} from '@agoric/vow';
* @import {Remote, Vow, VowTools} from '@agoric/vow';
* @import {AnyJson} from '@agoric/cosmic-proto';
* @import {TxBody} from '@agoric/cosmic-proto/cosmos/tx/v1beta1/tx.js';
* @import {LocalIbcAddress, RemoteIbcAddress} from '@agoric/vats/tools/ibc-utils.js';
Expand Down Expand Up @@ -103,11 +103,11 @@ export const prepareChainAccountKit = (zone, { watch, asVow }) =>
},
getBalance(_denom) {
// UNTIL https://github.com/Agoric/agoric-sdk/issues/9326
throw new Error('not yet implemented');
return asVow(() => Fail`'not yet implemented'`);
},
getBalances() {
// UNTIL https://github.com/Agoric/agoric-sdk/issues/9326
throw new Error('not yet implemented');
return asVow(() => Fail`'not yet implemented'`);
},
getLocalAddress() {
return NonNullish(
Expand All @@ -125,9 +125,7 @@ export const prepareChainAccountKit = (zone, { watch, asVow }) =>
return this.state.port;
},
executeTx() {
return asVow(() => {
throw new Error('not yet implemented');
});
return asVow(() => Fail`'not yet implemented'`);
},
/**
* Submit a transaction on behalf of the remote account for execution on
Expand All @@ -142,8 +140,6 @@ export const prepareChainAccountKit = (zone, { watch, asVow }) =>
executeEncodedTx(msgs, opts) {
return asVow(() => {
const { connection } = this.state;
// TODO #9281 do not throw synchronously when returning a promise; return a rejected Vow
/// see https://github.com/Agoric/agoric-sdk/pull/9454#discussion_r1626898694
if (!connection) throw Fail`connection not available`;
return watch(
E(connection).send(makeTxPacket(msgs, opts)),
Expand All @@ -163,10 +159,8 @@ export const prepareChainAccountKit = (zone, { watch, asVow }) =>
// - retrieve assets?
// - revoke the port?
const { connection } = this.state;
// TODO #9281 do not throw synchronously when returning a promise; return a rejected Vow
/// see https://github.com/Agoric/agoric-sdk/pull/9454#discussion_r1626898694
if (!connection) throw Fail`connection not available`;
return watch(E(connection).close());
return E(connection).close();
});
},
/**
Expand All @@ -176,19 +170,16 @@ export const prepareChainAccountKit = (zone, { watch, asVow }) =>
*/
getPurse(brand) {
console.log('getPurse got', brand);
return asVow(() => {
throw new Error('not yet implemented');
});
return asVow(() => Fail`'not yet implemented'`);
},
},
connectionHandler: {
/**
* @param {Remote<Connection>} connection
* @param {LocalIbcAddress} localAddr
* @param {RemoteIbcAddress} remoteAddr
* @returns {PromiseVow<void>}
*/
onOpen(connection, localAddr, remoteAddr) {
async onOpen(connection, localAddr, remoteAddr) {
trace(`ICA Channel Opened for ${localAddr} at ${remoteAddr}`);
this.state.connection = connection;
this.state.remoteAddress = remoteAddr;
Expand All @@ -200,18 +191,15 @@ export const prepareChainAccountKit = (zone, { watch, asVow }) =>
chainId: this.state.chainId,
addressEncoding: 'bech32',
});
return Promise.resolve(watch(undefined));
},
/**
* @param {Remote<Connection>} _connection
* @param {unknown} reason
* @returns {PromiseVow<void>}
*/
onClose(_connection, reason) {
async onClose(_connection, reason) {
trace(`ICA Channel closed. Reason: ${reason}`);
// FIXME handle connection closing https://github.com/Agoric/agoric-sdk/issues/9192
// XXX is there a scenario where a connection will unexpectedly close? _I think yes_
return Promise.resolve(watch(undefined));
},
},
},
Expand Down
6 changes: 3 additions & 3 deletions packages/orchestration/src/typeGuards.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { VowShape } from '@agoric/vow';
import { M } from '@endo/patterns';

/**
* Used for IBC Channel Connections that only send outgoing packets. If your
* channel expects incoming packets, please extend this interface to include
* `onReceive`.
* Used for IBC Channel Connections that only send outgoing transactions. If
* your channel expects incoming transactions, please extend this interface to
* include the `onReceive` handler.
*/
export const OutboundConnectionHandlerI = M.interface(
'OutboundConnectionHandler',
Expand Down
4 changes: 2 additions & 2 deletions packages/vow/src/vow-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { M, matches } from '@endo/patterns';

/**
* @import {PassableCap} from '@endo/pass-style';
* @import {VowPayload, Vow} from './types.js';
* @import {VowPayload, Vow, PromiseVow} from './types.js';
* @import {MakeVowKit} from './vow.js';
*/

Expand Down Expand Up @@ -81,7 +81,7 @@ export const makeAsVow = makeVowKit => {
* Helper function that coerces the result of a function to a Vow. Helpful
* for scenarios like a synchronously thrown error.
* @template {any} T
* @param {(...args: any[]) => Vow<Awaited<T>> | Awaited<T>} fn
* @param {(...args: any[]) => Vow<Awaited<T>> | Awaited<T> | PromiseVow<T>} fn
* @returns {Vow<Awaited<T>>}
*/
const asVow = fn => {
Expand Down

0 comments on commit f409a8d

Please sign in to comment.