threefoldtecharchive / rivine

Blockchain technology for creating custom chains.
Apache License 2.0
22 stars 12 forks source link

a universal redis API for the data replicator #183

Open GlenDC opened 6 years ago

GlenDC commented 6 years ago

When KDS asked to provide a data replication feature which only uses one Redis interface, it was also proposed that this redis interface has to be exposed by an actual redis server. That was never a hard requirement. The only hard requirement is that all commands/controls happen via a single interface, a redis-protocol API, such that the user only has to use a redis client, know the right commands and how to use those, and that it's it. It allows the user to use the data replication feature from any language, as long as a redis client is available. Great.

So far we did solved this quite cumbersome by having a redis server, which both the user and the server use. Making the redis server somehow the controlling piece here, in-between rivine and the user. While it kinda worked, it has several disadvantages:

On top of these advantages it doesn't make our life easier at all. It doesn't save us time at all.

Therefore I propose that the datastorage module exposes (over TCP) a redis-protocol (see: https://redis.io/topics/protocol) server, which exposes the following API:

SELECT <namespace> // -> void
GET <shortID> // -> (data []byte)
GET <longID> // -> (data []byte [, shortID []byte])
                        // second result param is only returned if available
REGISTER <data> // -> (longID []byte)
SUBSCRIBE <namespace> [startTime|startBlockHeight] // start replicating the given namespace
UNSUBSCRIBE <namespace>

As you can see the API is relatively small, and our codebase won't really change too much (I mean you will have/want to refactor, but you will be able to reuse most of your logic, just better, cleaner and easier structured).

While the redis protocol is easy enough to implement, you don't have to do so. There are libs available that do what we need I think (e.g. https://github.com/phuongdo/go-redisproto), and starting a TCP server in Golang is as easy as eating candy. So the only work you'll have is to define those commands and link them to handlers (hopefully a good help makes this easy as well).

Further you're database will be able to become a lot simpler. For Redis you could still to choose a hashmap if desired, but we wouldn't need the channel stuff there anymore. Details need to be worked out though.


An alternative API could also be:

GET <namespace> <shortID> // -> (data []byte)
GET <namespace> <longID> // -> (data []byte [, shortID []byte])
                        // second result param is only returned if available
REGISTER <namespace> <data> // -> (longID []byte)
SUBSCRIBE <namespace> [startTime|startBlockHeight] // start replicating the given namespace
UNSUBSCRIBE <namespace>

I leave it up to you to decide.

LeeSmet commented 6 years ago

So if I get this right:

Do we attach the tcp listener to the datastore specifically, or do we make a "global" redis api which functions similarly to the current http api and which could eventually be extended to work with all modules?

GlenDC commented 6 years ago

Do we attach the tcp listener to the datastore specifically

this