-
Notifications
You must be signed in to change notification settings - Fork 195
Improvements to Event Cache #1947
Comments
Thanks for starting this discussion ! A few general thoughts:
|
Just starting to look at this. For what it's worth, IndexedDB support is pretty solid. Have a few questions before I start on this:
EDIT: Whoops, I think I misunderstood. You want this implemented in the Mobile is a challenge. React-native doesn't support @nick mentioned setting this up as its own |
Kind of writing up a bit of an API spec to get an idea of what needs to be built. Thoughts? EventCache APIFor the purpose of this document, we'll call the primary class Usage
|
Thanks Mike, here are a few comments:
Here's how I'd like to use the API for a Marketplace EventCache: Get all events for listing 123: Get all events for pertaining to user 0xabc...: Get all events for offer '123-456' (listing 123, offer 456): Get all ListingCreated events for user 0xabc...: Get all OfferCreated events for listing 123 or 456: Get all Seller initiated events for listing 123: Here's how IdentityEvents would be used:
It would be nice if we could also offer a web3.js compatible API, though filters would only work when given a specific event: Get all ListingCreated events for user 0xabc...: Get all OfferCreated events for listing 123 or 456: This is less important and not needed for v1, though worth bearing in mind. |
We can skip the params arg, and derive that from the provided Should be able to mimic the For backwards compat, should I still include those calls I have above or scrub them all in favor of |
We can skip the params arg and derive from the provided event names, sure. We can start off by getting allEvents, however I think that's only a short term solution. If we ever get to millions of events we'll no longer be able to rely on that. Not an issue for right now but worth thinking about while we're in the design phase. Ideally we'd like to get to a point where we're only downloading events needed to show the data the UI needs. Lets not bother with |
If anyone wants to take an early peek to make sure the API looks good, see #1975. So far it has the in-memory and the IndexedDB backends. I'm going to start the Postgres backend either tonight or tomorrow, but had a couple of questions before I do:
I generally prefer having the user provide a DSN, then having the package create the necessary schema. That said I'd still rather to stick with the current style of things and stay in-line with what's being done now. I'm also not super familiar with what will be using this package, so I'd only be guessing how it'll be used with the Postgres backend. |
This is looking awesome @mikeshultz.
Great work! |
FYI there are now some puppeteer integration tests on the marketplace dapp we can use to test the finished implementation. Can be run with |
@tomlinton Thanks for the info and links! @nick puppeteer looks nice. Right now my IndexedDB tests are mocked using |
@nick I missed your mention of array params in your previous post(that you also just mentioned in discord). The logic to do that would be a bit spicy. For instance, what would it do for this hypothetical request:
Would it match everything as an OR, and run 4 separate queries anyway? AND on all of them would never return results. But maybe you need to AND between the first of each and second of each. Maybe it would be better for the consumer of this package to just run separate queries for each, anyway, since that's what each backend would be doing anyway (except maybe Postgres)? Maybe a good compromise would be creating a custom method for this purpose. For example...
That way it could be limited to one param and be explicit in its behavior. |
The web3.js getPastEvents method will treat arrays as 'OR' I think:
I think if 'event' were passed in, it'd have to work as an 'AND' though... so the following:
would be
would be It gets tricker when we want to specify an offer though as the offer ID is dependent on the listing ID. Maybe something like:
would be |
hrm, I didn't notice that in the web3 API. This is going to get pretty dirty, especially outside of the postgres backend. I'll see what I can do. |
Dexie.js has good filtering support but might be too heavy weight 🤔 |
Think we can call this done now 🙂 |
The Origin marketplace dapp is able to function with only 2 dependencies: an Ethereum node and an IPFS server. Every time a user takes an action such as creating a listing or making an offer, an event is emitted on the Marketplace contract that follows the following structure:
Event(index party, indexd listingId, indexd offerId, ipfsHash)
The first 3 parameters as well as the name of the event are 'indexed', meaning they can be filtered on when requesting data from the Ethereum node. These indexed parameters are known as 'topics'. topic 0 is the hashed event name and topics 1-3 are the parameters marked as 'indexed'.
Having events indexed in this way is a useful property as we can now easily request events pertaining to a certain individual or particular listing or offer.
For example, to retrieve all events related to listing 345, we would issue a query for all Marketplace events with topics
*, *, 345, *
(any event name, any party, listing 345, and any offer). To retrieve all events created by a particular user, we would query for*, userWallet, *, *
. To retrieve all listings created by a particular user we would query forListingCreated, userWallet, *, *
.In order to build up the current state of a listing or offer, Origin has an event source module which, given a listing ID and/or offer ID will first fetch all related events from the Ethereum node, then pull all related data from IPFS, then construct the current 'state' of the listing or offer by using what is essentially map/reduce.
This presents several problems:
In order to address these issues, we have an eventCache module which does the following:
Although this has worked well so far, storing every single event locally in the browser is not
scalable. The easy way out would be to simply request data from a centralized server... but we should try to avoid that.
Instead, I think we should make our event cache smarter and more capable. Here's my proposed features of the new event cache:
Store events in IndexedDB
IndexedDB has a higher storage quota that localStorage and could be more performant when querying data as it has SQL-like syntax. Our existing solution marshals the JSON into localStorage then calls filters it by comparing every item, which is inefficient on large datasets.
Be contract agnostic
The existing eventCache has methods for listings and offers, but we can instead try to be contract agnostic so the same cache can be used by other contracts (such as IdentityEvents) and even other projects.
Only request data we need
We should only query events relating to data the user is interested in rather than getting everything.
The text was updated successfully, but these errors were encountered: