Dunder the message JSON API provides gateway for sharing messages directly out of you console. For best experience you may want to write your own tool for sharing messages or just use curl :)
Don't consider Dunder as stable, everything may change. Beware software may also contain bugs!
Some tips how to get service up and running. Please familiarize yourself
with Makefile
it may provide some helpful commands. Note that go.mod
file
requires Go 1.13, it should be safe to build service with older versions.
TLS certs for development are stored under tls
directory. Use
mkcert to generate valid local
certificates.
$ mkcert -install
$ mkcert -cert-file ./tls/crt.pem -key-file ./tls/key.pem dunder.io "*.dunder.io" dunder.test localhost 127.0.0.1 ::1
Currently Dunder provides only CockroachDB
backend. However implementation
is based on gorm so potentially it's possible to port
it to other databases. Note that some inline SQL may be compatible only with Postgres.
Run docker-compose up
to setup local CockroachDB cluster. Setup provides useful
web interface at port 8080
. Please consult docker-compose.yaml
as some folder may
need to be created to mount cluster data volumes.
Docker compose includes prebuild version of dunder
connected with database cluster and it's available
immediately after docker compose startup on port 9000
. In this scenario dunder
would use
defaultdb
database.
If you want to swap to other database you need to create it and set --cockroach.database
flag.
For example using postgresql-client
:
$ createdb -p 26257 -h localhost -U root -e live_database
You could achieve same result by using CockroachDB
repl client:
$ cockroach sql --insecure
And running create database SQL statement.
Service main code is placed under cmd
directory. You need to build
binary and run service.
$ go build -o bin/dunder cmd/*.go
$ ./bin/dunder --config_file config.yaml
You can also get information about available command line options by running:
$ ./bin/dunder -h
Usage of dunder:
--use_tls Connection uses TLS if true, else plain TCP
--port int GRPC port
--log_level string Options: debug, info, warn, error, fatal, panic
--cockroach.host string
--cockroach.should_migrate
--cockroach.debug
--cockroach.database string
--cockroach.user string
--tls.crt string TLS certificate file path
--tls.key string TLS key file path
--config_file string provide a config file path
-h, --help print this help menu
Related flags could be set with config file config.yaml
:
use_tls: true
tls:
crt: tls/crt.pem
key: tls/key.pem
port: 9000
debug: true
cockroach:
host: localhost
should_migrate: true
debug: true
database: live_database
user: root
Post some messges:
$ TOKEN=`echo -n $USER | base64 -w0`
$ curl -d '{"text": "some text", "hashtags":["tag1", "tag2"]}' -H"Authorization: Bearer ${TOKEN}" https://localhost:9000/message
$ curl -d '{"text": "some other text", "hashtags":["tag3", "tag4"]}' -H"Authorization: Bearer ${TOKEN}" https://localhost:9000/message
User header is required and users are dynamically created as Dunder don't provide yet any endpoints for user management.
Get some messages using eg. tag query:
$ curl https://localhost:9000/message?hashtag=tag1
Filter options:
- from_date - from date range
- to_date - to date range
- limit - response limit (default 100)
- cursor - pagination cursor
- user_name - filter by user name
- hashtag - filter by hashtag
Trends provides at smallest minute granularity statistics of messages occurrence with option
to filter with hashtag
. Aggregation option would accept time.Duration format and
it's minimal value is 1m
.
$ curl "https://localhost:9000/trend?to_date=2019-09-23&aggregation=1m&from_date=2019-09-22&hashtag=dummy3"
Trends options:
- from_date - from date range
- to_date - to date range
- hashtag - filter by hashtag
- aggregation - aggregation period
This section describes some further development steps to release Dunder to public.
Standard method is to build helm chart and scale service using Kubernetes cluster.
Some reference implementation could be look up here.
CockroachDB could be also easily setup and maintained in K8S cluster.
Usually it's good choice to use ingress-nginx
controller with TLS termination.
Simplest approach is to use LetEncrypt
and cert-manager
to manage TLS along with DNS resolver.
Certificates are stored directly in K8S secrets and can be mounted to service or used by ingress
controller if TLS termination is made on LB level.
Kubernetes rolling update and load balancing requires decently working health checks for readiness and liveness probes. This enable load balancing and rolling update to happen properly with no down times or missed requests.
With OpenCensus it's easy to implement tracing and monitoring layers, to gain insights on usage and performance
of service. By using OpenCensus
one would have a lot of options for exporting tracing and metrics. For even deeper dive
if application is deployed on GKE there is very nice tool for profiling with pprof
so flame charts are directly available on Stackdriver page. Some additional reference.
Current implementation may need some further optimization around SQL statements to get best efficiency at scale. Probably some geo partitioning tricks would be useful along with distributing app servers in different locations around world.
The nature of instant message sharing systems is that user would usually expect to see some recent messages. System could then evict old messages to other storage where they can be searched eg. using only batch jobs, so live database would be efficient in querying most recent messages.
Tweaking efficiency even further I would recommend to look at CQRS and Event Sourcing techniques eg. using SQL database as hard storage (command part) and piping commands down to eg. Redis cluster where query part would occur.
In current state Dunder is missing a lot of tests. Most critical path repository implementation have same parts covered (and may be improved). As this repository is just POC it would require some extra effort to cover all paths. However design of service allows for easy testing with eg. mockery since service layers depend on interface implementations rather then on concrete structures.