Skip to content
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

7502 followup: factor out factory #7519

Merged
merged 8 commits into from
May 2, 2023
Merged

7502 followup: factor out factory #7519

merged 8 commits into from
May 2, 2023

Conversation

turadg
Copy link
Member

@turadg turadg commented Apr 25, 2023

Description

#7502 fixed an error in zcfMint kind restoration during reincarnation. While investigating it became clear that kind redefinitions could be simplified.

This turns the singleton into an Exo class, sharing the behavior across instances.

Using that prepare it also factors out the ZCFMintFactory and uses the maker directly.

Finally it has some types and helpers to support the change.

Of note: it switches some function declarations back to the @param style because I learned that tsc doesn't check the arguments at the callsite without it.

Security Considerations

noop

Scaling Considerations

noop

Documentation Considerations

noop

Testing Considerations

CI. Incidentally, while iterating there were some bugs that none of the Zoe package tests caught. Only the vats bootstrapTests did.

@turadg turadg changed the title 7502 followup: refactor factory 7502 followup: factor out factory Apr 26, 2023
@turadg turadg marked this pull request as ready for review April 26, 2023 15:15
Copy link
Contributor

@Chris-Hibbert Chris-Hibbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, with questions.

If merging this isn't urgent, I'd like to wait to give @erights a chance to say why we thought using singletons was a better choice for this case, and whether things have changed so it makes sense to switch to prepareDurable.

Comment on lines 36 to 37
mintGains: M.call(AmountKeywordRecordShape, M.any()).returns(SeatShape),
burnLosses: M.call(AmountKeywordRecordShape, M.any()).returns(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets use M.remotable('zcfSeat') instead of M.any().

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah I had postponed expressing the optionalality of the seat arg:

* @callback ZCFMintMintGains
* @param {AmountKeywordRecord} gains
* @param {ZCFSeat} [zcfSeat]
* @returns {ZCFSeat}
*/

Turns out ZCFMintI has this same issue. I'll fix that and re-use it.

* baggage for the state of the zcfMint, makes a durableZcfMint from that
* baggage, and registers that baggage to be revived with the factory.
*/
// TODO refactor zcfMintFactory uses to makeZcfMint directly
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was this supposed to be "zcfMintFactory used to makeZcfMint directly"? Otherwise I'm not able to make sense of it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was an interim state in the refactoring

Comment on lines 77 to 78
/** @type {Amount<AssetKind>} */ total,
/** @type {Amount<AssetKind>} */ amountToAdd,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see how these types help when add's only use is to be passed to .reduce(). gains is already typed because it is externally visible.

Are they here out of habit, or do they improve maintainability somehow?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interim state. a subsequent commit had,

        /** @type {(total: Amount, amountToAdd: Amount) => Amount}  */
        const add = (total, amountToAdd) =>
          AmountMath.add(total, amountToAdd, mintyBrand);

the type declaration doesn't add much but imo it's still better

Copy link
Member

@erights erights left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used the opportunity to see if it reminded me of why I may once have objected. I found one possible reason, and explain in the comments why I am not concerned in this case. I got through the whole review without being reminded of any other reason. With @Chris-Hibbert also not remembering or having any reason to object...

LGTM, thanks!

* @param {(exit?: undefined) => { zcfSeat: any; userSeat: Promise<UserSeat> }} makeEmptySeatKit
* @param {ZcfMintReallocator} reallocator
*/
export const prepareDurableZcfMint = (
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When a function is already named prepare* and takes a baggage as first argument, the "Durable" part of the name is implied, and so redundant. My naming habit is to say "durable" explicitly only when the name does not start with "prepare".

Suggested change
export const prepareDurableZcfMint = (
export const prepareZcfMint = (

/** @type {ZcfMintReallocator} */ reallocator,
/**
*
* @param {import('@agoric/vat-data').Baggage} zcfBaggage
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for restoring the @param convention, even if for a different reason. With the two side by side, I again find the @param convention more readable. YMMV

Comment on lines -53 to -56
const add = (total, amountToAdd) =>
AmountMath.add(total, amountToAdd, mintyBrand);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This curried add is an example of an issue that pushed me towards lexical state. When there are a lot of these curried functions, that curry over per-instance state, then having to recreate them per method invocation(!) is oppressive.

In this case, it is one function whose creation code only needs to be repeated twice. It does happen on each invocation of the relevant methods, rather than per singleton kind creation. But these are low frequency methods. So in this case, neither the readability cost nor the runtime cost should hold us back from switching to an exoClass.

(Continuing the review, looking for other red flags against using an exoClass for these.)

mintyDisplayInfo.assetKind,
);

return { empty, keyword, mintyBrand, zoeMint, mintyIssuerRecord };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's funny that, as lexical state, the redundancy of mintyBrand vs mintyIssuerRecord.brand would not bother me. As persistent state, it itches, because I think of exoClass instance state as something with potentially high cardinality. In this case, of course, the cardinality is not actually any higher.

Another reason to avoid the redundancy is because it is more persistent state that could be inconsistent. The prior baggage form did not have the redundancy, but (like add) it is because it only needed to restore the lexical variable per kind, not per invocation.

So I'm on the fence. No change suggested. But if the above changed your mind, that change would be fine with me too.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree. PTAAL at b200a59

@turadg turadg force-pushed the 7502-refactor branch 3 times, most recently from bb91d3e to f3c4bf7 Compare April 27, 2023 17:26
Copy link
Contributor

@Chris-Hibbert Chris-Hibbert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's a left-over nit that didn't get sent with the rest of my review. As it says: "if convenient".

/** @type { (exit?: undefined) => { zcfSeat: any; userSeat: Promise<UserSeat> }} */ makeEmptySeatKit,
/** @type {ZcfMintReallocator} */ reallocator,
/**
*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drop blank line if convenient.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok will do in my rebase cleanup

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got 'em all 0160e2f

@turadg turadg added the automerge:no-update (expert!) Automatically merge without updates label May 2, 2023
@mergify mergify bot merged commit 3a98338 into master May 2, 2023
@mergify mergify bot deleted the 7502-refactor branch May 2, 2023 19:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
automerge:no-update (expert!) Automatically merge without updates
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants