Skip to content

Conversation

@peterbroadhurst
Copy link
Contributor

@peterbroadhurst peterbroadhurst commented Mar 14, 2022

Currently there is no clean way to query messages on a given topic in the same order that they were dispatched to your application.

More worryingly, we imply that the that you might be able to use the confirmed timestamp of the message as a substitute, as currently it's unique for each message. The problem with this is that timestamps are not guaranteed to only move forwards.

The only object in FireFly that is guaranteed to have a sequence you can rely upon is events, and these are delivered to your application with the message in-line in the case of a message_confirmed event. We just added ?fetchreferences (thanks @shorsher) on the /events resource collection, so that's an important piece of the puzzle. So with the extra change in this PR, if you want to query messages on a topic in the order they happened you just do:

  • /api/v1/namespaces/{NS}/events?type=message_confirmed&fetchreferences&topic=MYTOPIC
    • Reverse sequence is the default sort - so you can add &sort=sequence for ascending

Note that this does not return you the data (there is no 2nd tier ?fetchdata option). Adding this needs extra discussion as we'd drawn a line in the sand of only doing one level of auto-fetching for you. However, the convenience of fetchdata might be the exception that proves the rule 🤔

In a PR chain with #599

  • Adds topic as am indexed field on events (64 chars)
  • If there are multiple topics in a message to generates multiple message_confirmed events.
  • Batch confirms messages, so multiple messages have the same confirmed timestamp
  • Updates E2E test to apply the best practice described above
  • Topics are assigned to all events, including non-message events (table below)

This has two benefits:

  1. Performance increase due to being able to do a blanket set of confirmed to a single timestamp in the aggregator.
  2. The ability to query all history for a topic cleanly in applications, without implicitly relying on positively increasing timestamps, and being confident its the same order that the confirmations happened in and your application was delivered the events.

Topic events

Event Topic Comment
message_confirmed Message Topic The key use case of filtering on topic
message_rejected Message Topic "
blockchain_event_received ff_batch_pin for the built-in batch pin listener.
Topic from the listener if specified.
Listener ID as string otherwise
Setting a topic on the blockchain listener allows grouping of multiple events into a common stream
token_pool_confirmed Token pool ID as string Allows querying of all events on a token pool
token_transfer_confirmed Token pool ID as string "
token_transfer_op_failed Token pool ID as string "
token_approval_confirmed Token pool ID as string "
namespace_confirmed ff_definitions Catch all topic for FireFly system definitions
datatype_confirmed ff_definitions "
identity_confirmed ff_definitions "
identity_updated ff_definitions "
contract_interface_confirmed ff_definitions "
contract_api_confirmed ff_definitions "

@codecov-commenter
Copy link

codecov-commenter commented Mar 14, 2022

Codecov Report

Merging #600 (169b71f) into main (0598d9f) will not change coverage.
The diff coverage is 100.00%.

@@            Coverage Diff            @@
##              main      #600   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          305       305           
  Lines        18297     18357   +60     
=========================================
+ Hits         18297     18357   +60     
Impacted Files Coverage Δ
pkg/fftypes/contract_listener.go 100.00% <ø> (ø)
internal/batch/batch_processor.go 100.00% <100.00%> (ø)
internal/config/config.go 100.00% <100.00%> (ø)
...ternal/database/sqlcommon/contractlisteners_sql.go 100.00% <100.00%> (ø)
internal/database/sqlcommon/event_sql.go 100.00% <100.00%> (ø)
...ternal/definitions/definition_handler_contracts.go 100.00% <100.00%> (ø)
...nternal/definitions/definition_handler_datatype.go 100.00% <100.00%> (ø)
...l/definitions/definition_handler_identity_claim.go 100.00% <100.00%> (ø)
.../definitions/definition_handler_identity_update.go 100.00% <100.00%> (ø)
...ternal/definitions/definition_handler_namespace.go 100.00% <100.00%> (ø)
... and 20 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0598d9f...169b71f. Read the comment docs.

…e messages to dispatched

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>
if err := bp.database.InsertEvent(ctx, event); err != nil {
return err
for _, topic := range msg.Header.Topics {
// One event per topic
Copy link
Contributor

Choose a reason for hiding this comment

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

Nothing inherently wrong with this, but it's one of those things that will need to be clearly release-noted. For any apps that use multiple topics, they'll suddenly get more events with copies of the same data - so it just reinforces the need for those apps to have idempotent data processing.

awrichar
awrichar previously approved these changes Mar 15, 2022
Copy link
Contributor

@awrichar awrichar left a comment

Choose a reason for hiding this comment

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

There are 2 weird things about this PR:

  1. We have two new fields ("topic" and "tag") that are unused for the majority of our event types (although they are used with the most common event type "message_confirmed")
  2. Messages with multiple topics will now get multiple events emitted which all contain the same message

But after staring and thinking for a while, I'm on the same page - I think the benefits (being able to query messages in order and being able to batch update the messages upon confirmation) outweigh the weirdness. I haven't been able to think of any alternate proposal that's better on those two counts. Since the weird things are mostly only visible to "advanced" users and are fairly easy to explain/design around, I'm on board.

@awrichar
Copy link
Contributor

Alright the one other alternative that occurs to me is adding a special query param to /messages that would indicate "fetch confirmed messages only, and in the order they were confirmed, by doing a join with the events table".

In theory, that would eliminate the need to put topic and tag on the events table...I think.

While "topic" is clearly useful in terms of ordering, "tag" is not
quite as justifiable to be duplicated this way.

Signed-off-by: Andrew Richardson <andrew.richardson@kaleido.io>
@awrichar
Copy link
Contributor

Pushed a proposal to pull "tag" back out, as I think it's harder to justify here. If we can take this a step further and make "topic" meaningful for events other than messages, then it feels like a more complete change.

@awrichar awrichar dismissed their stale review March 18, 2022 22:13

Removing approval as it sounds like this is going to continue evolving a bit longer

@peterbroadhurst
Copy link
Contributor Author

peterbroadhurst commented Mar 19, 2022

Further updates being added:

  • Allowing a custom topic to specified on the blockchain listener, and passed to the FireFly event emitted
  • Addressing an existing TODO in the code to add a blockchain listener lookup cache to event manager

…ents

Signed-off-by: Peter Broadhurst <peter.broadhurst@kaleido.io>
Comment on lines +52 to +56
func (em *eventManager) getChainListenerByIDCached(ctx context.Context, id *fftypes.UUID) (*fftypes.ContractListener, error) {
return em.getChainListenerCached(fmt.Sprintf("id:%s", id), func() (*fftypes.ContractListener, error) {
return em.database.GetContractListenerByID(ctx, id)
})
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Glad to see this can take advantage of caching now

@peterbroadhurst peterbroadhurst merged commit 224ea30 into hyperledger:main Mar 20, 2022
@peterbroadhurst peterbroadhurst deleted the batch-confirm branch March 20, 2022 01:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants