-
Notifications
You must be signed in to change notification settings - Fork 14
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
refactor token state management #25
Conversation
By putting the responsibility of calling |
/// | ||
/// If the closure returns an error, the transaction is dropped atomically and no change is | ||
/// observed on token state. | ||
pub fn transaction<F, Res>(&mut self, f: F) -> Result<Res> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is interesting but not quite perfect.
- Ideally don't expose the token state directly to Token users
- Users can still use the API outside a transaction.
I think this method makes a pretty good internal transaction helper. I.e. call it from within Token methods so they are atomic, but don't expose it publicly. So I reckon make it non-pub
for this PR, fixing (1).
I'm not sure 2 is a serious problem, but would be nice to address. For application-level transactions, we'd need the callback parameter to be Token or a new TokenTxn trait. If callers strictly used that, it would kinda give (2).
@@ -266,76 +279,99 @@ where | |||
))); | |||
} | |||
|
|||
let mut state = self.load_state(); | |||
let _old_state = self.state.clone(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused (for now)
Before addressing the cleanup of tests and additional test-cases from the feedback in #24, I wanted to refactor the API provided by
Token
for loading and saving itself to the blockstore.There was some awkwardness noted around the
Token::new
pattern. This change addresses that with the following options:Token::new
Token::load
Previously, every call to a method on Token would cause state to be loaded and written to the blockstore. Now, by holding a TokenState rather than a Cid pointing to it, we can cache state changes in memory. This pushes the onus of persistance onto the library consumer, requiring a call to
Token::flush
to persist state changes into the blockstore. This should be a more flexible API allowing greater control of when expensive read/writes occur and enables batching of transactions.This incidentally highlights a previously uncaught bug in
transfer
andburn
which made multiple sequential calls to changeTokenState
. If any step within the transaction fails, previous changes would need to be reverted. This is much easier done if changes are made in memory rather than being committed to the blockstore. To help this, aToken::transaction
method is introduced to help us write atomic transactions.