mirror of
https://github.com/tendermint/tendermint.git
synced 2026-02-05 11:31:16 +00:00
1 line
25 KiB
JavaScript
1 line
25 KiB
JavaScript
(window.webpackJsonp=window.webpackJsonp||[]).push([[129],{697:function(e,t,n){"use strict";n.r(t);var a=n(1),i=Object(a.a)({},(function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[n("h1",{attrs:{id:"adr-065-custom-event-indexing"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#adr-065-custom-event-indexing"}},[e._v("#")]),e._v(" ADR 065: Custom Event Indexing")]),e._v(" "),n("ul",[n("li",[n("a",{attrs:{href:"#adr-065-custom-event-indexing"}},[e._v("ADR 065: Custom Event Indexing")]),e._v(" "),n("ul",[n("li",[n("a",{attrs:{href:"#changelog"}},[e._v("Changelog")])]),e._v(" "),n("li",[n("a",{attrs:{href:"#status"}},[e._v("Status")])]),e._v(" "),n("li",[n("a",{attrs:{href:"#context"}},[e._v("Context")])]),e._v(" "),n("li",[n("a",{attrs:{href:"#alternative-approaches"}},[e._v("Alternative Approaches")])]),e._v(" "),n("li",[n("a",{attrs:{href:"#decision"}},[e._v("Decision")])]),e._v(" "),n("li",[n("a",{attrs:{href:"#detailed-design"}},[e._v("Detailed Design")]),e._v(" "),n("ul",[n("li",[n("a",{attrs:{href:"#eventsink"}},[e._v("EventSink")])]),e._v(" "),n("li",[n("a",{attrs:{href:"#supported-sinks"}},[e._v("Supported Sinks")]),e._v(" "),n("ul",[n("li",[n("a",{attrs:{href:"#kveventsink"}},[n("code",[e._v("KVEventSink")])])]),e._v(" "),n("li",[n("a",{attrs:{href:"#psqleventsink"}},[n("code",[e._v("PSQLEventSink")])])])])]),e._v(" "),n("li",[n("a",{attrs:{href:"#configuration"}},[e._v("Configuration")])])])]),e._v(" "),n("li",[n("a",{attrs:{href:"#future-improvements"}},[e._v("Future Improvements")])]),e._v(" "),n("li",[n("a",{attrs:{href:"#consequences"}},[e._v("Consequences")]),e._v(" "),n("ul",[n("li",[n("a",{attrs:{href:"#positive"}},[e._v("Positive")])]),e._v(" "),n("li",[n("a",{attrs:{href:"#negative"}},[e._v("Negative")])]),e._v(" "),n("li",[n("a",{attrs:{href:"#neutral"}},[e._v("Neutral")])])])]),e._v(" "),n("li",[n("a",{attrs:{href:"#references"}},[e._v("References")])])])])]),e._v(" "),n("h2",{attrs:{id:"changelog"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#changelog"}},[e._v("#")]),e._v(" Changelog")]),e._v(" "),n("ul",[n("li",[e._v("April 1, 2021: Initial Draft (@alexanderbez)")]),e._v(" "),n("li",[e._v("April 28, 2021: Specify search capabilities are only supported through the KV indexer (@marbar3778)")]),e._v(" "),n("li",[e._v("May 19, 2021: Update the SQL schema and the eventsink interface (@jayt106)")]),e._v(" "),n("li",[e._v("Aug 30, 2021: Update the SQL schema and the psql implementation (@creachadair)")]),e._v(" "),n("li",[e._v("Oct 5, 2021: Clarify goals and implementation changes (@creachadair)")])]),e._v(" "),n("h2",{attrs:{id:"status"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#status"}},[e._v("#")]),e._v(" Status")]),e._v(" "),n("p",[e._v("Accepted")]),e._v(" "),n("h2",{attrs:{id:"context"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#context"}},[e._v("#")]),e._v(" Context")]),e._v(" "),n("p",[e._v("Currently, Tendermint Core supports block and transaction event indexing through\nthe "),n("code",[e._v("tx_index.indexer")]),e._v(" configuration. Events are captured in transactions and\nare indexed via a "),n("code",[e._v("TxIndexer")]),e._v(" type. Events are captured in blocks, specifically\nfrom "),n("code",[e._v("BeginBlock")]),e._v(" and "),n("code",[e._v("EndBlock")]),e._v(" application responses, and are indexed via a\n"),n("code",[e._v("BlockIndexer")]),e._v(" type. Both of these types are managed by a single "),n("code",[e._v("IndexerService")]),e._v("\nwhich is responsible for consuming events and sending those events off to be\nindexed by the respective type.")]),e._v(" "),n("p",[e._v("In addition to indexing, Tendermint Core also supports the ability to query for\nboth indexed transaction and block events via Tendermint's RPC layer. The ability\nto query for these indexed events facilitates a great multitude of upstream client\nand application capabilities, e.g. block explorers, IBC relayers, and auxiliary\ndata availability and indexing services.")]),e._v(" "),n("p",[e._v("Currently, Tendermint only supports indexing via a "),n("code",[e._v("kv")]),e._v(" indexer, which is supported\nby an underlying embedded key/value store database. The "),n("code",[e._v("kv")]),e._v(" indexer implements\nits own indexing and query mechanisms. While the former is somewhat trivial,\nproviding a rich and flexible query layer is not as trivial and has caused many\nissues and UX concerns for upstream clients and applications.")]),e._v(" "),n("p",[e._v("The fragile nature of the proprietary "),n("code",[e._v("kv")]),e._v(" query engine and the potential\nperformance and scaling issues that arise when a large number of consumers are\nintroduced, motivate the need for a more robust and flexible indexing and query\nsolution.")]),e._v(" "),n("h2",{attrs:{id:"alternative-approaches"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#alternative-approaches"}},[e._v("#")]),e._v(" Alternative Approaches")]),e._v(" "),n("p",[e._v("With regards to alternative approaches to a more robust solution, the only serious\ncontender that was considered was to transition to using "),n("a",{attrs:{href:"https://www.sqlite.org/index.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("SQLite"),n("OutboundLink")],1),e._v(".")]),e._v(" "),n("p",[e._v("While the approach would work, it locks us into a specific query language and\nstorage layer, so in some ways it's only a bit better than our current approach.\nIn addition, the implementation would require the introduction of CGO into the\nTendermint Core stack, whereas right now CGO is only introduced depending on\nthe database used.")]),e._v(" "),n("h2",{attrs:{id:"decision"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#decision"}},[e._v("#")]),e._v(" Decision")]),e._v(" "),n("p",[e._v("We will adopt a similar approach to that of the Cosmos SDK's "),n("code",[e._v("KVStore")]),e._v(" state\nlistening described in "),n("a",{attrs:{href:"https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-038-state-listening.md",target:"_blank",rel:"noopener noreferrer"}},[e._v("ADR-038"),n("OutboundLink")],1),e._v(".")]),e._v(" "),n("p",[e._v("We will implement the following changes:")]),e._v(" "),n("ul",[n("li",[e._v("Introduce a new interface, "),n("code",[e._v("EventSink")]),e._v(", that all data sinks must implement.")]),e._v(" "),n("li",[e._v("Augment the existing "),n("code",[e._v("tx_index.indexer")]),e._v(" configuration to now accept a series\nof one or more indexer types, i.e., sinks.")]),e._v(" "),n("li",[e._v("Combine the current "),n("code",[e._v("TxIndexer")]),e._v(" and "),n("code",[e._v("BlockIndexer")]),e._v(" into a single "),n("code",[e._v("KVEventSink")]),e._v("\nthat implements the "),n("code",[e._v("EventSink")]),e._v(" interface.")]),e._v(" "),n("li",[e._v("Introduce an additional "),n("code",[e._v("EventSink")]),e._v(" implementation that is backed by\n"),n("a",{attrs:{href:"https://www.postgresql.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("PostgreSQL"),n("OutboundLink")],1),e._v(".\n"),n("ul",[n("li",[e._v("Implement the necessary schemas to support both block and transaction event indexing.")])])]),e._v(" "),n("li",[e._v("Update "),n("code",[e._v("IndexerService")]),e._v(" to use a series of "),n("code",[e._v("EventSinks")]),e._v(".")])]),e._v(" "),n("p",[e._v("In addition:")]),e._v(" "),n("ul",[n("li",[n("p",[e._v("The Postgres indexer implementation will "),n("em",[e._v("not")]),e._v(" implement the proprietary "),n("code",[e._v("kv")]),e._v("\nquery language. Users wishing to write queries against the Postgres indexer\nwill connect to the underlying DBMS directly and use SQL queries based on the\nindexing schema.")]),e._v(" "),n("p",[e._v("Future custom indexer implementations will not be required to support the\nproprietary query language either.")])]),e._v(" "),n("li",[n("p",[e._v("For now, the existing "),n("code",[e._v("kv")]),e._v(" indexer will be left in place with its current\nquery support, but will be marked as deprecated in a subsequent release, and\nthe documentation will be updated to encourage users who need to query the\nevent index to migrate to the Postgres indexer.")])]),e._v(" "),n("li",[n("p",[e._v("In the future we may remove the "),n("code",[e._v("kv")]),e._v(" indexer entirely, or replace it with a\ndifferent implementation; that decision is deferred as future work.")])]),e._v(" "),n("li",[n("p",[e._v("In the future, we may remove the index query endpoints from the RPC service\nentirely; that decision is deferred as future work, but recommended.")])])]),e._v(" "),n("h2",{attrs:{id:"detailed-design"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#detailed-design"}},[e._v("#")]),e._v(" Detailed Design")]),e._v(" "),n("h3",{attrs:{id:"eventsink"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#eventsink"}},[e._v("#")]),e._v(" EventSink")]),e._v(" "),n("p",[e._v("We introduce the "),n("code",[e._v("EventSink")]),e._v(" interface type that all supported sinks must implement.\nThe interface is defined as follows:")]),e._v(" "),n("tm-code-block",{staticClass:"codeblock",attrs:{language:"go",base64:"dHlwZSBFdmVudFNpbmsgaW50ZXJmYWNlIHsKICBJbmRleEJsb2NrRXZlbnRzKHR5cGVzLkV2ZW50RGF0YU5ld0Jsb2NrSGVhZGVyKSBlcnJvcgogIEluZGV4VHhFdmVudHMoW10qYWJjaS5UeFJlc3VsdCkgZXJyb3IKCiAgU2VhcmNoQmxvY2tFdmVudHMoY29udGV4dC5Db250ZXh0LCAqcXVlcnkuUXVlcnkpIChbXWludDY0LCBlcnJvcikKICBTZWFyY2hUeEV2ZW50cyhjb250ZXh0LkNvbnRleHQsICpxdWVyeS5RdWVyeSkgKFtdKmFiY2kuVHhSZXN1bHQsIGVycm9yKQoKICBHZXRUeEJ5SGFzaChbXWJ5dGUpICgqYWJjaS5UeFJlc3VsdCwgZXJyb3IpCiAgSGFzQmxvY2soaW50NjQpIChib29sLCBlcnJvcikKCiAgVHlwZSgpIEV2ZW50U2lua1R5cGUKICBTdG9wKCkgZXJyb3IKfQo="}}),e._v(" "),n("p",[e._v("The "),n("code",[e._v("IndexerService")]),e._v(" will accept a list of one or more "),n("code",[e._v("EventSink")]),e._v(" types. During\nthe "),n("code",[e._v("OnStart")]),e._v(" method it will call the appropriate APIs on each "),n("code",[e._v("EventSink")]),e._v(" to\nindex both block and transaction events.")]),e._v(" "),n("h3",{attrs:{id:"supported-sinks"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#supported-sinks"}},[e._v("#")]),e._v(" Supported Sinks")]),e._v(" "),n("p",[e._v("We will initially support two "),n("code",[e._v("EventSink")]),e._v(" types out of the box.")]),e._v(" "),n("h4",{attrs:{id:"kveventsink"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#kveventsink"}},[e._v("#")]),e._v(" "),n("code",[e._v("KVEventSink")])]),e._v(" "),n("p",[e._v("This type of "),n("code",[e._v("EventSink")]),e._v(" is a combination of the "),n("code",[e._v("TxIndexer")]),e._v(" and "),n("code",[e._v("BlockIndexer")]),e._v("\nindexers, both of which are backed by a single embedded key/value database.")]),e._v(" "),n("p",[e._v("A bulk of the existing business logic will remain the same, but the existing APIs\nmapped to the new "),n("code",[e._v("EventSink")]),e._v(" API. Both types will be removed in favor of a single\n"),n("code",[e._v("KVEventSink")]),e._v(" type.")]),e._v(" "),n("p",[e._v("The "),n("code",[e._v("KVEventSink")]),e._v(" will be the only "),n("code",[e._v("EventSink")]),e._v(" enabled by default, so from a UX\nperspective, operators should not notice a difference apart from a configuration\nchange.")]),e._v(" "),n("p",[e._v("We omit "),n("code",[e._v("EventSink")]),e._v(" implementation details as it should be fairly straightforward\nto map the existing business logic to the new APIs.")]),e._v(" "),n("h4",{attrs:{id:"psqleventsink"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#psqleventsink"}},[e._v("#")]),e._v(" "),n("code",[e._v("PSQLEventSink")])]),e._v(" "),n("p",[e._v("This type of "),n("code",[e._v("EventSink")]),e._v(" indexes block and transaction events into a "),n("a",{attrs:{href:"https://www.postgresql.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("PostgreSQL"),n("OutboundLink")],1),e._v(".\ndatabase. We define and automatically migrate the following schema when the\n"),n("code",[e._v("IndexerService")]),e._v(" starts.")]),e._v(" "),n("p",[e._v("The postgres eventsink will not support "),n("code",[e._v("tx_search")]),e._v(", "),n("code",[e._v("block_search")]),e._v(", "),n("code",[e._v("GetTxByHash")]),e._v(" and "),n("code",[e._v("HasBlock")]),e._v(".")]),e._v(" "),n("tm-code-block",{staticClass:"codeblock",attrs:{language:"sql",base64:"LS0gVGFibGUgRGVmaW5pdGlvbiAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgotLSBUaGUgYmxvY2tzIHRhYmxlIHJlY29yZHMgbWV0YWRhdGEgYWJvdXQgZWFjaCBibG9jay4KLS0gVGhlIGJsb2NrIHJlY29yZCBkb2VzIG5vdCBpbmNsdWRlIGl0cyBldmVudHMgb3IgdHJhbnNhY3Rpb25zIChzZWUgdHhfcmVzdWx0cykuCkNSRUFURSBUQUJMRSBibG9ja3MgKAogIHJvd2lkICAgICAgQklHU0VSSUFMIFBSSU1BUlkgS0VZLAoKICBoZWlnaHQgICAgIEJJR0lOVCBOT1QgTlVMTCwKICBjaGFpbl9pZCAgIFZBUkNIQVIgTk9UIE5VTEwsCgogIC0tIFdoZW4gdGhpcyBibG9jayBoZWFkZXIgd2FzIGxvZ2dlZCBpbnRvIHRoZSBzaW5rLCBpbiBVVEMuCiAgY3JlYXRlZF9hdCBUSU1FU1RBTVBUWiBOT1QgTlVMTCwKCiAgVU5JUVVFIChoZWlnaHQsIGNoYWluX2lkKQopOwoKLS0gSW5kZXggYmxvY2tzIGJ5IGhlaWdodCBhbmQgY2hhaW4sIHNpbmNlIHdlIG5lZWQgdG8gcmVzb2x2ZSBibG9jayBJRHMgd2hlbgotLSBpbmRleGluZyB0cmFuc2FjdGlvbiByZWNvcmRzIGFuZCB0cmFuc2FjdGlvbiBldmVudHMuCkNSRUFURSBJTkRFWCBpZHhfYmxvY2tzX2hlaWdodF9jaGFpbiBPTiBibG9ja3MoaGVpZ2h0LCBjaGFpbl9pZCk7CgotLSBUaGUgdHhfcmVzdWx0cyB0YWJsZSByZWNvcmRzIG1ldGFkYXRhIGFib3V0IHRyYW5zYWN0aW9uIHJlc3VsdHMuICBOb3RlIHRoYXQKLS0gdGhlIGV2ZW50cyBmcm9tIGEgdHJhbnNhY3Rpb24gYXJlIHN0b3JlZCBzZXBhcmF0ZWx5LgpDUkVBVEUgVEFCTEUgdHhfcmVzdWx0cyAoCiAgcm93aWQgQklHU0VSSUFMIFBSSU1BUlkgS0VZLAoKICAtLSBUaGUgYmxvY2sgdG8gd2hpY2ggdGhpcyB0cmFuc2FjdGlvbiBiZWxvbmdzLgogIGJsb2NrX2lkIEJJR0lOVCBOT1QgTlVMTCBSRUZFUkVOQ0VTIGJsb2Nrcyhyb3dpZCksCiAgLS0gVGhlIHNlcXVlbnRpYWwgaW5kZXggb2YgdGhlIHRyYW5zYWN0aW9uIHdpdGhpbiB0aGUgYmxvY2suCiAgaW5kZXggSU5URUdFUiBOT1QgTlVMTCwKICAtLSBXaGVuIHRoaXMgcmVzdWx0IHJlY29yZCB3YXMgbG9nZ2VkIGludG8gdGhlIHNpbmssIGluIFVUQy4KICBjcmVhdGVkX2F0IFRJTUVTVEFNUFRaIE5PVCBOVUxMLAogIC0tIFRoZSBoZXgtZW5jb2RlZCBoYXNoIG9mIHRoZSB0cmFuc2FjdGlvbi4KICB0eF9oYXNoIFZBUkNIQVIgTk9UIE5VTEwsCiAgLS0gVGhlIHByb3RvYnVmIHdpcmUgZW5jb2Rpbmcgb2YgdGhlIFR4UmVzdWx0IG1lc3NhZ2UuCiAgdHhfcmVzdWx0IEJZVEVBIE5PVCBOVUxMLAoKICBVTklRVUUgKGJsb2NrX2lkLCBpbmRleCkKKTsKCi0tIFRoZSBldmVudHMgdGFibGUgcmVjb3JkcyBldmVudHMuIEFsbCBldmVudHMgKGJvdGggYmxvY2sgYW5kIHRyYW5zYWN0aW9uKSBhcmUKLS0gYXNzb2NpYXRlZCB3aXRoIGEgYmxvY2sgSUQ7IHRyYW5zYWN0aW9uIGV2ZW50cyBhbHNvIGhhdmUgYSB0cmFuc2FjdGlvbiBJRC4KQ1JFQVRFIFRBQkxFIGV2ZW50cyAoCiAgcm93aWQgQklHU0VSSUFMIFBSSU1BUlkgS0VZLAoKICAtLSBUaGUgYmxvY2sgYW5kIHRyYW5zYWN0aW9uIHRoaXMgZXZlbnQgYmVsb25ncyB0by4KICAtLSBJZiB0eF9pZCBpcyBOVUxMLCB0aGlzIGlzIGEgYmxvY2sgZXZlbnQuCiAgYmxvY2tfaWQgQklHSU5UIE5PVCBOVUxMIFJFRkVSRU5DRVMgYmxvY2tzKHJvd2lkKSwKICB0eF9pZCAgICBCSUdJTlQgTlVMTCBSRUZFUkVOQ0VTIHR4X3Jlc3VsdHMocm93aWQpLAoKICAtLSBUaGUgYXBwbGljYXRpb24tZGVmaW5lZCB0eXBlIGxhYmVsIGZvciB0aGUgZXZlbnQuCiAgdHlwZSBWQVJDSEFSIE5PVCBOVUxMCik7CgotLSBUaGUgYXR0cmlidXRlcyB0YWJsZSByZWNvcmRzIGV2ZW50IGF0dHJpYnV0ZXMuCkNSRUFURSBUQUJMRSBhdHRyaWJ1dGVzICgKICAgZXZlbnRfaWQgICAgICBCSUdJTlQgTk9UIE5VTEwgUkVGRVJFTkNFUyBldmVudHMocm93aWQpLAogICBrZXkgICAgICAgICAgIFZBUkNIQVIgTk9UIE5VTEwsIC0tIGJhcmUga2V5CiAgIGNvbXBvc2l0ZV9rZXkgVkFSQ0hBUiBOT1QgTlVMTCwgLS0gY29tcG9zZWQgdHlwZS5rZXkKICAgdmFsdWUgICAgICAgICBWQVJDSEFSIE5VTEwsCgogICBVTklRVUUgKGV2ZW50X2lkLCBrZXkpCik7CgotLSBBIGpvaW5lZCB2aWV3IG9mIGV2ZW50cyBhbmQgdGhlaXIgYXR0cmlidXRlcy4gRXZlbnRzIHRoYXQgZG8gbm90IGhhdmUgYW55Ci0tIGF0dHJpYnV0ZXMgYXJlIHJlcHJlc2VudGVkIGFzIGEgc2luZ2xlIHJvdyB3aXRoIGVtcHR5IGtleSBhbmQgdmFsdWUgZmllbGRzLgpDUkVBVEUgVklFVyBldmVudF9hdHRyaWJ1dGVzIEFTCiAgU0VMRUNUIGJsb2NrX2lkLCB0eF9pZCwgdHlwZSwga2V5LCBjb21wb3NpdGVfa2V5LCB2YWx1ZQogIEZST00gZXZlbnRzIExFRlQgSk9JTiBhdHRyaWJ1dGVzIE9OIChldmVudHMucm93aWQgPSBhdHRyaWJ1dGVzLmV2ZW50X2lkKTsKCi0tIEEgam9pbmVkIHZpZXcgb2YgYWxsIGJsb2NrIGV2ZW50cyAodGhvc2UgaGF2aW5nIHR4X2lkIE5VTEwpLgpDUkVBVEUgVklFVyBibG9ja19ldmVudHMgQVMKICBTRUxFQ1QgYmxvY2tzLnJvd2lkIGFzIGJsb2NrX2lkLCBoZWlnaHQsIGNoYWluX2lkLCB0eXBlLCBrZXksIGNvbXBvc2l0ZV9rZXksIHZhbHVlCiAgRlJPTSBibG9ja3MgSk9JTiBldmVudF9hdHRyaWJ1dGVzIE9OIChibG9ja3Mucm93aWQgPSBldmVudF9hdHRyaWJ1dGVzLmJsb2NrX2lkKQogIFdIRVJFIGV2ZW50X2F0dHJpYnV0ZXMudHhfaWQgSVMgTlVMTDsKCi0tIEEgam9pbmVkIHZpZXcgb2YgYWxsIHRyYW5zYWN0aW9uIGV2ZW50cy4KQ1JFQVRFIFZJRVcgdHhfZXZlbnRzIEFTCiAgU0VMRUNUIGhlaWdodCwgaW5kZXgsIGNoYWluX2lkLCB0eXBlLCBrZXksIGNvbXBvc2l0ZV9rZXksIHZhbHVlLCB0eF9yZXN1bHRzLmNyZWF0ZWRfYXQKICBGUk9NIGJsb2NrcyBKT0lOIHR4X3Jlc3VsdHMgT04gKGJsb2Nrcy5yb3dpZCA9IHR4X3Jlc3VsdHMuYmxvY2tfaWQpCiAgSk9JTiBldmVudF9hdHRyaWJ1dGVzIE9OICh0eF9yZXN1bHRzLnJvd2lkID0gZXZlbnRfYXR0cmlidXRlcy50eF9pZCkKICBXSEVSRSBldmVudF9hdHRyaWJ1dGVzLnR4X2lkIElTIE5PVCBOVUxMOwo="}}),e._v(" "),n("p",[e._v("The "),n("code",[e._v("PSQLEventSink")]),e._v(" will implement the "),n("code",[e._v("EventSink")]),e._v(" interface as follows\n(some details omitted for brevity):")]),e._v(" "),n("tm-code-block",{staticClass:"codeblock",attrs:{language:"go",base64:"ZnVuYyBOZXdFdmVudFNpbmsoY29ublN0ciwgY2hhaW5JRCBzdHJpbmcpICgqRXZlbnRTaW5rLCBlcnJvcikgewoJZGIsIGVyciA6PSBzcWwuT3Blbihkcml2ZXJOYW1lLCBjb25uU3RyKQoJLy8gLi4uCgoJcmV0dXJuICZhbXA7RXZlbnRTaW5rewoJCXN0b3JlOiAgIGRiLAoJCWNoYWluSUQ6IGNoYWluSUQsCgl9LCBuaWwKfQoKZnVuYyAoZXMgKkV2ZW50U2luaykgSW5kZXhCbG9ja0V2ZW50cyhoIHR5cGVzLkV2ZW50RGF0YU5ld0Jsb2NrSGVhZGVyKSBlcnJvciB7Cgl0cyA6PSB0aW1lLk5vdygpLlVUQygpCgoJcmV0dXJuIHJ1bkluVHJhbnNhY3Rpb24oZXMuc3RvcmUsIGZ1bmModHggKnNxbC5UeCkgZXJyb3IgewoJCS8vIEFkZCB0aGUgYmxvY2sgdG8gdGhlIGJsb2NrcyB0YWJsZSBhbmQgcmVwb3J0IGJhY2sgaXRzIHJvdyBJRCBmb3IgdXNlCgkJLy8gaW4gaW5kZXhpbmcgdGhlIGV2ZW50cyBmb3IgdGhlIGJsb2NrLgoJCWJsb2NrSUQsIGVyciA6PSBxdWVyeVdpdGhJRCh0eCwgYApJTlNFUlQgSU5UTyBibG9ja3MgKGhlaWdodCwgY2hhaW5faWQsIGNyZWF0ZWRfYXQpCiAgVkFMVUVTICgkMSwgJDIsICQzKQogIE9OIENPTkZMSUNUIERPIE5PVEhJTkcKICBSRVRVUk5JTkcgcm93aWQ7CmAsIGguSGVhZGVyLkhlaWdodCwgZXMuY2hhaW5JRCwgdHMpCgkJLy8gLi4uCgoJCS8vIEluc2VydCB0aGUgc3BlY2lhbCBibG9jayBtZXRhLWV2ZW50IGZvciBoZWlnaHQuCgkJaWYgZXJyIDo9IGluc2VydEV2ZW50cyh0eCwgYmxvY2tJRCwgMCwgW11hYmNpLkV2ZW50ewoJCQltYWtlSW5kZXhlZEV2ZW50KHR5cGVzLkJsb2NrSGVpZ2h0S2V5LCBmbXQuU3ByaW50KGguSGVhZGVyLkhlaWdodCkpLAoJCX0pOyBlcnIgIT0gbmlsIHsKCQkJcmV0dXJuIGZtdC5FcnJvcmYoJnF1b3Q7YmxvY2sgbWV0YS1ldmVudHM6ICV3JnF1b3Q7LCBlcnIpCgkJfQoJCS8vIEluc2VydCBhbGwgdGhlIGJsb2NrIGV2ZW50cy4gT3JkZXIgaXMgaW1wb3J0YW50IGhlcmUsCgkJaWYgZXJyIDo9IGluc2VydEV2ZW50cyh0eCwgYmxvY2tJRCwgMCwgaC5SZXN1bHRCZWdpbkJsb2NrLkV2ZW50cyk7IGVyciAhPSBuaWwgewoJCQlyZXR1cm4gZm10LkVycm9yZigmcXVvdDtiZWdpbi1ibG9jayBldmVudHM6ICV3JnF1b3Q7LCBlcnIpCgkJfQoJCWlmIGVyciA6PSBpbnNlcnRFdmVudHModHgsIGJsb2NrSUQsIDAsIGguUmVzdWx0RW5kQmxvY2suRXZlbnRzKTsgZXJyICE9IG5pbCB7CgkJCXJldHVybiBmbXQuRXJyb3JmKCZxdW90O2VuZC1ibG9jayBldmVudHM6ICV3JnF1b3Q7LCBlcnIpCgkJfQoJCXJldHVybiBuaWwKCX0pCn0KCmZ1bmMgKGVzICpFdmVudFNpbmspIEluZGV4VHhFdmVudHModHhycyBbXSphYmNpLlR4UmVzdWx0KSBlcnJvciB7Cgl0cyA6PSB0aW1lLk5vdygpLlVUQygpCgoJZm9yIF8sIHR4ciA6PSByYW5nZSB0eHJzIHsKCQkvLyBFbmNvZGUgdGhlIHJlc3VsdCBtZXNzYWdlIGluIHByb3RvYnVmIHdpcmUgZm9ybWF0IGZvciBpbmRleGluZy4KCQlyZXN1bHREYXRhLCBlcnIgOj0gcHJvdG8uTWFyc2hhbCh0eHIpCgkJLy8gLi4uCgoJCS8vIEluZGV4IHRoZSBoYXNoIG9mIHRoZSB1bmRlcmx5aW5nIHRyYW5zYWN0aW9uIGFzIGEgaGV4IHN0cmluZy4KCQl0eEhhc2ggOj0gZm10LlNwcmludGYoJnF1b3Q7JVgmcXVvdDssIHR5cGVzLlR4KHR4ci5UeCkuSGFzaCgpKQoKCQlpZiBlcnIgOj0gcnVuSW5UcmFuc2FjdGlvbihlcy5zdG9yZSwgZnVuYyh0eCAqc3FsLlR4KSBlcnJvciB7CgkJCS8vIEZpbmQgdGhlIGJsb2NrIGFzc29jaWF0ZWQgd2l0aCB0aGlzIHRyYW5zYWN0aW9uLgoJCQlibG9ja0lELCBlcnIgOj0gcXVlcnlXaXRoSUQodHgsIGAKU0VMRUNUIHJvd2lkIEZST00gYmxvY2tzIFdIRVJFIGhlaWdodCA9ICQxIEFORCBjaGFpbl9pZCA9ICQyOwpgLCB0eHIuSGVpZ2h0LCBlcy5jaGFpbklEKQoJCQkvLyAuLi4KCgkJCS8vIEluc2VydCBhIHJlY29yZCBmb3IgdGhpcyB0eF9yZXN1bHQgYW5kIGNhcHR1cmUgaXRzIElEIGZvciBpbmRleGluZyBldmVudHMuCgkJCXR4SUQsIGVyciA6PSBxdWVyeVdpdGhJRCh0eCwgYApJTlNFUlQgSU5UTyB0eF9yZXN1bHRzIChibG9ja19pZCwgaW5kZXgsIGNyZWF0ZWRfYXQsIHR4X2hhc2gsIHR4X3Jlc3VsdCkKICBWQUxVRVMgKCQxLCAkMiwgJDMsICQ0LCAkNSkKICBPTiBDT05GTElDVCBETyBOT1RISU5HCiAgUkVUVVJOSU5HIHJvd2lkOwpgLCBibG9ja0lELCB0eHIuSW5kZXgsIHRzLCB0eEhhc2gsIHJlc3VsdERhdGEpCgkJCS8vIC4uLgoKCQkJLy8gSW5zZXJ0IHRoZSBzcGVjaWFsIHRyYW5zYWN0aW9uIG1ldGEtZXZlbnRzIGZvciBoYXNoIGFuZCBoZWlnaHQuCgkJCWlmIGVyciA6PSBpbnNlcnRFdmVudHModHgsIGJsb2NrSUQsIHR4SUQsIFtdYWJjaS5FdmVudHsKCQkJCW1ha2VJbmRleGVkRXZlbnQodHlwZXMuVHhIYXNoS2V5LCB0eEhhc2gpLAoJCQkJbWFrZUluZGV4ZWRFdmVudCh0eXBlcy5UeEhlaWdodEtleSwgZm10LlNwcmludCh0eHIuSGVpZ2h0KSksCgkJCX0pOyBlcnIgIT0gbmlsIHsKCQkJCXJldHVybiBmbXQuRXJyb3JmKCZxdW90O2luZGV4aW5nIHRyYW5zYWN0aW9uIG1ldGEtZXZlbnRzOiAldyZxdW90OywgZXJyKQoJCQl9CgkJCS8vIEluZGV4IGFueSBldmVudHMgcGFja2FnZWQgd2l0aCB0aGUgdHJhbnNhY3Rpb24uCgkJCWlmIGVyciA6PSBpbnNlcnRFdmVudHModHgsIGJsb2NrSUQsIHR4SUQsIHR4ci5SZXN1bHQuRXZlbnRzKTsgZXJyICE9IG5pbCB7CgkJCQlyZXR1cm4gZm10LkVycm9yZigmcXVvdDtpbmRleGluZyB0cmFuc2FjdGlvbiBldmVudHM6ICV3JnF1b3Q7LCBlcnIpCgkJCX0KCQkJcmV0dXJuIG5pbAoKCQl9KTsgZXJyICE9IG5pbCB7CgkJCXJldHVybiBlcnIKCQl9Cgl9CglyZXR1cm4gbmlsCn0KCi8vIFNlYXJjaEJsb2NrRXZlbnRzIGlzIG5vdCBpbXBsZW1lbnRlZCBieSB0aGlzIHNpbmssIGFuZCByZXBvcnRzIGFuIGVycm9yIGZvciBhbGwgcXVlcmllcy4KZnVuYyAoZXMgKkV2ZW50U2luaykgU2VhcmNoQmxvY2tFdmVudHMoY3R4IGNvbnRleHQuQ29udGV4dCwgcSAqcXVlcnkuUXVlcnkpIChbXWludDY0LCBlcnJvcikKCi8vIFNlYXJjaFR4RXZlbnRzIGlzIG5vdCBpbXBsZW1lbnRlZCBieSB0aGlzIHNpbmssIGFuZCByZXBvcnRzIGFuIGVycm9yIGZvciBhbGwgcXVlcmllcy4KZnVuYyAoZXMgKkV2ZW50U2luaykgU2VhcmNoVHhFdmVudHMoY3R4IGNvbnRleHQuQ29udGV4dCwgcSAqcXVlcnkuUXVlcnkpIChbXSphYmNpLlR4UmVzdWx0LCBlcnJvcikKCi8vIEdldFR4QnlIYXNoIGlzIG5vdCBpbXBsZW1lbnRlZCBieSB0aGlzIHNpbmssIGFuZCByZXBvcnRzIGFuIGVycm9yIGZvciBhbGwgcXVlcmllcy4KZnVuYyAoZXMgKkV2ZW50U2luaykgR2V0VHhCeUhhc2goaGFzaCBbXWJ5dGUpICgqYWJjaS5UeFJlc3VsdCwgZXJyb3IpCgovLyBIYXNCbG9jayBpcyBub3QgaW1wbGVtZW50ZWQgYnkgdGhpcyBzaW5rLCBhbmQgcmVwb3J0cyBhbiBlcnJvciBmb3IgYWxsIHF1ZXJpZXMuCmZ1bmMgKGVzICpFdmVudFNpbmspIEhhc0Jsb2NrKGggaW50NjQpIChib29sLCBlcnJvcikK"}}),e._v(" "),n("h3",{attrs:{id:"configuration"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#configuration"}},[e._v("#")]),e._v(" Configuration")]),e._v(" "),n("p",[e._v("The current "),n("code",[e._v("tx_index.indexer")]),e._v(" configuration would be changed to accept a list\nof supported "),n("code",[e._v("EventSink")]),e._v(" types instead of a single value.")]),e._v(" "),n("p",[e._v("Example:")]),e._v(" "),n("tm-code-block",{staticClass:"codeblock",attrs:{language:"toml",base64:"W3R4X2luZGV4XQoKaW5kZXhlciA9IFsKICAmcXVvdDtrdiZxdW90OywKICAmcXVvdDtwc3FsJnF1b3Q7Cl0K"}}),e._v(" "),n("p",[e._v("If the "),n("code",[e._v("indexer")]),e._v(" list contains the "),n("code",[e._v("null")]),e._v(" indexer, then no indexers will be used\nregardless of what other values may exist.")]),e._v(" "),n("p",[e._v("Additional configuration parameters might be required depending on what event\nsinks are supplied to "),n("code",[e._v("tx_index.indexer")]),e._v(". The "),n("code",[e._v("psql")]),e._v(" will require an additional\nconnection configuration.")]),e._v(" "),n("tm-code-block",{staticClass:"codeblock",attrs:{language:"toml",base64:"W3R4X2luZGV4XQoKaW5kZXhlciA9IFsKICAmcXVvdDtrdiZxdW90OywKICAmcXVvdDtwc3FsJnF1b3Q7Cl0KCnBxc3FsX2Nvbm4gPSAmcXVvdDtwb3N0Z3Jlc3FsOi8vJmx0O3VzZXImZ3Q7OiZsdDtwYXNzd29yZCZndDtAJmx0O2hvc3QmZ3Q7OiZsdDtwb3J0Jmd0Oy8mbHQ7ZGImZ3Q7PyZsdDtvcHRzJmd0OyZxdW90Owo="}}),e._v(" "),n("p",[e._v("Any invalid or misconfigured "),n("code",[e._v("tx_index")]),e._v(" configuration should yield an error as\nearly as possible.")]),e._v(" "),n("h2",{attrs:{id:"future-improvements"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#future-improvements"}},[e._v("#")]),e._v(" Future Improvements")]),e._v(" "),n("p",[e._v('Although not technically required to maintain feature parity with the current\nexisting Tendermint indexer, it would be beneficial for operators to have a method\nof performing a "re-index". Specifically, Tendermint operators could invoke an\nRPC method that allows the Tendermint node to perform a re-indexing of all block\nand transaction events between two given heights, H'),n("sub",[e._v("1")]),e._v(" and H"),n("sub",[e._v("2")]),e._v(",\nso long as the block store contains the blocks and transaction results for all\nthe heights specified in a given range.")]),e._v(" "),n("h2",{attrs:{id:"consequences"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#consequences"}},[e._v("#")]),e._v(" Consequences")]),e._v(" "),n("h3",{attrs:{id:"positive"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#positive"}},[e._v("#")]),e._v(" Positive")]),e._v(" "),n("ul",[n("li",[e._v("A more robust and flexible indexing and query engine for indexing and search\nblock and transaction events.")]),e._v(" "),n("li",[e._v("The ability to not have to support a custom indexing and query engine beyond\nthe legacy "),n("code",[e._v("kv")]),e._v(" type.")]),e._v(" "),n("li",[e._v("The ability to offload/proxy indexing and querying to the underling sink.")]),e._v(" "),n("li",[e._v('Scalability and reliability that essentially comes "for free" from the underlying\nsink, if it supports it.')])]),e._v(" "),n("h3",{attrs:{id:"negative"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#negative"}},[e._v("#")]),e._v(" Negative")]),e._v(" "),n("ul",[n("li",[e._v("The need to support multiple and potentially a growing set of custom "),n("code",[e._v("EventSink")]),e._v("\ntypes.")])]),e._v(" "),n("h3",{attrs:{id:"neutral"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#neutral"}},[e._v("#")]),e._v(" Neutral")]),e._v(" "),n("h2",{attrs:{id:"references"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#references"}},[e._v("#")]),e._v(" References")]),e._v(" "),n("ul",[n("li",[n("a",{attrs:{href:"https://github.com/cosmos/cosmos-sdk/blob/master/docs/architecture/adr-038-state-listening.md",target:"_blank",rel:"noopener noreferrer"}},[e._v("Cosmos SDK ADR-038"),n("OutboundLink")],1)]),e._v(" "),n("li",[n("a",{attrs:{href:"https://www.postgresql.org/",target:"_blank",rel:"noopener noreferrer"}},[e._v("PostgreSQL"),n("OutboundLink")],1)]),e._v(" "),n("li",[n("a",{attrs:{href:"https://www.sqlite.org/index.html",target:"_blank",rel:"noopener noreferrer"}},[e._v("SQLite"),n("OutboundLink")],1)])])],1)}),[],!1,null,null,null);t.default=i.exports}}]); |