Open GlenDC opened 6 years ago
So if I get this right:
When starting the datastore, start a tcp server which listens for messages in redis protocol to controll it.
Remove controlling functions (SUBSCRIBE/UNSUBSCRIBE) from the database as this now only serves to store data.
Maybe implement a database using boltDB to remain in line with other modules and we seem to want to expose fetching the data from the redis api in the datastore as well.
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?
Do we attach the tcp listener to the datastore specifically
this
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:
HGET <namespace> <key>
to get a key in a namespace, whererivinec
CLI to get a transaction, to than know the shortID...HGET
, instead we could for example choose to implement namespaces as a thing that you have toSELECT
such that getting data is done using a normalGET <key>
;<key>
should be able to be both the long and short ID, where the shortID is returned together with the returned should a long ID be used, so that next time the shortID is known as well;PUBLISH replication subscribe:food
/PUBLISH replication unsubscribe:food
, while really what we want would be something like:SUBSCRIBE food
/UNSUBSCRIBE food
;0-db
instead ofredis
(which I'm sure we'll want), as that database does not support channels at all, and thus relying on it to play the controller (between rivine and client) is not going to happen, and it never will;REGISTER <data>
and it would return thelongID
as key;Rivine <=> db <-> user
, while really that flow should bedb <-> Rivine <-> user <->
;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: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:
I leave it up to you to decide.