-
Notifications
You must be signed in to change notification settings - Fork 242
Update batch logic to only store+hash the manifest #582
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
Conversation
Signed-off-by: Peter Broadhurst <peter.broadhurst@kaleido.io>
Signed-off-by: Peter Broadhurst <peter.broadhurst@kaleido.io>
Signed-off-by: Peter Broadhurst <peter.broadhurst@kaleido.io>
Signed-off-by: Peter Broadhurst <peter.broadhurst@kaleido.io>
pkg/fftypes/data.go
Outdated
| return nil | ||
| } | ||
| // For broadcast data the blob reference contains the "public" (shared storage) reference, which | ||
| // must have been allocated to this data item before sealing the batch. |
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 the operative decision for #568 - I'm still wondering if it's possible for the public reference to be removed from the batch hash altogether. Perhaps it could be stored on the Blob instead of on the BlobRef?
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.
It's mainly odd that private blob transfer happens after batch sealing, but public blob transfer must happen before batch sealing in order to include the IPFS ref. Seems like they should happen in the same order regardless.
When a node receives an IPFS ref, it does do some checking of the fetched contents to verify they match the blob hash before recording the blob as received. The question is whether this is "good enough" to say we can send IPFS refs without including them in the batch's hash proof.
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.
Seems like they should happen in the same order regardless.
While I agree the discrepancy is annoying - I do not think this is possible, as IPFS does not have a "messaging" capability. It's just a storage system. So the blockchain has to be the messaging system in this case.
Signed-off-by: Peter Broadhurst <peter.broadhurst@kaleido.io>
Signed-off-by: Peter Broadhurst <peter.broadhurst@kaleido.io>
Signed-off-by: Peter Broadhurst <peter.broadhurst@kaleido.io>
Signed-off-by: Peter Broadhurst <peter.broadhurst@kaleido.io>
…ache on upsert Signed-off-by: Peter Broadhurst <peter.broadhurst@kaleido.io>
Signed-off-by: Peter Broadhurst <peter.broadhurst@kaleido.io>
Signed-off-by: Peter Broadhurst <peter.broadhurst@kaleido.io>
Codecov Report
@@ Coverage Diff @@
## main #582 +/- ##
==========================================
Coverage 100.00% 100.00%
==========================================
Files 304 304
Lines 17544 17801 +257
==========================================
+ Hits 17544 17801 +257
Continue to review full report at Codecov.
|
Signed-off-by: Peter Broadhurst <peter.broadhurst@kaleido.io>
|
|
||
| var getStatusPins = &oapispec.Route{ | ||
| Name: "getStatusPins", | ||
| Path: "status/pins", |
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.
Why are these under status? Doesn't feel entirely like a "status" object to me since it's just a collection listing... I guess the alternative would be a root endpoint though. Open to anything really, just wanted to call it out.
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.
We could put them at the root, if we wanted to explain them in more detail as a first class object.
My thinking here was they are an internal read-only view of the state for problem diagnosis. Understand it's not perfect, and happy to discuss more.
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.
Shall be merging through the chain with this here, but with an open-ness to move it in a future commit
| msgIDs[i] = msg.Header.ID | ||
| // We don't want to have to read the DB again if we want to query for the batch ID, or pins, | ||
| // so ensure the copy in our cache gets updated. | ||
| bp.data.UpdateMessageIfCached(ctx, msg) |
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.
Want to make sure it's OK that we update the batchID in the cache before we write the batchID to the database itself (ie in case we somehow fail to update the database)... I think it's OK and we would come back around and try to write the same batchID on the second try. Just wanted to put a note because I was staring at this for a bit.
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.
Yep, the only way to avoid this would be to push all of the cache updating (in all cases) to post-commit actions.
I convinced myself that wasn't required, but happy to discuss more.
| for di, dataRef := range msg.Data { | ||
| msgData[di] = dataByID[*dataRef.ID] | ||
| if msgData[di] == nil || !msgData[di].Hash.Equals(dataRef.Hash) { | ||
| log.L(ctx).Debugf("Message '%s' in batch '%s' - data not in-line in batch id='%s' hash='%s'", msg.Header.ID, batch.ID, dataRef.ID, dataRef.Hash) |
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.
Should this be higher than debug? Is this an expected situation?
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.
The architecture prior to this code change allows it.
e.g. you could send some data to a party, then send a message referring to that data, without sending that data again.
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.
A specific example would be a broadcast, followed by a private message.
| fftypes.OpTypeDataExchangeBatchSend) | ||
| op.Input = fftypes.JSONObject{ | ||
| "batch": tw.Batch.ID, | ||
| } |
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 going to be overwritten by addBatchSendInputs below
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.
Sorry, think this was a merge error
awrichar
left a comment
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.
Looks good - marking approved, although I did leave a few comments inline that are worth a look before you decide to merge.
Signed-off-by: Peter Broadhurst <peter.broadhurst@kaleido.io>
Resolves #506
A few notes on the implementation.
Improvements related to performance:
txwas added to the manifest to include in the hashtopicswere needed for thisImprovements related to debug:
GET/status/pinscollection to peekinside the pins statusMigration:
Versionin manifest used to distinguish this, and provide future extensibilityPotential follow-on work:
fetchreferencesparam to events api #587 to use the message cachebatchcache - to help the aggregator logic when managing pinstransactioncache - to help addfetchreferencesparam to events api #587 event enrichmentGetMessageByIDcallsMessage/data cache implementation notes
Messages have fields that are mutable, in two categories
state- you cannot rely on the cache for theseFor (2) the cache provides a set of
CacheReadOptionmodifiers that makes it safe to query the cache, even if the cache we slow to update asynchronously (active/active cluster being the ultimate example here, but from code inspection this is possible in the current cache).If you use
CRORequestBatchIDthen the cache will return a miss, if there is noBatchIDset.If you use
CRORequirePinsthen the cache will return a miss, if the number of pins does not match the number of topics in the message.